/* Weblance Design Gallery, white theme (Ivan 10-12): a white page, near-black text, light-grey cards
   with hairline edges, a light-grey pill on the current section and a dark pill for the call to action. No glows and no
   haze, so the only strong colour on the page is the screens. The near-black is the wordmark's own ink.
   Layout (Ivan 10-11): a gallery shell. The sidebar on the left holds the lockup, the section menu (Animations today;
   each new section is one more row in it) and the link to weblancestudios.com at its foot; the page sits in the main
   area on the right. At 900 px and under the sidebar turns into a top bar and the link goes back to the foot of the page.
   Served at /gallery/assets/gallery.css, so every URL in here is absolute under /gallery. */
@font-face{font-family:"Mona Sans";src:url("/gallery/assets/fonts/MonaSans-latin.woff2") format("woff2");font-weight:200 900;font-stretch:75% 125%;font-display:swap}
/* --ink-2 is the quieter text (6:1 on white, 5:1 on the pill); --field is the edge of a box you type in, kept at 3.4:1
   (the least a form control's edge may have) where the decorative hairlines are much lighter. */
:root{
  --paper:#fff;
  --ink:#0f1523;
  --ink-2:#5f6370;
  --card:#f4f4f5;
  --line:#e4e4e7;
  --pill:#ececee;
  --field:#8b8b94;
  --pad:clamp(16px,3.8vw,72px);
  --side:clamp(248px,15vw,284px);
  --ease:cubic-bezier(.2,.7,.2,1);
}
*{box-sizing:border-box}
html{background:var(--paper);color-scheme:light;-webkit-text-size-adjust:100%;scrollbar-color:#c9cacf var(--paper)}
body{margin:0;font-family:"Mona Sans",system-ui,sans-serif;font-stretch:100%;color:var(--ink);line-height:1.5;-webkit-font-smoothing:antialiased}
::selection{background:#d9dce3;color:var(--ink)}
a{color:inherit;-webkit-tap-highlight-color:transparent}
:focus-visible{outline:2px solid var(--ink);outline-offset:5px;border-radius:8px}

/* The shell: the sidebar stays put while the main area scrolls. The footer (the link to weblancestudios.com) is pinned
   to the foot of the sidebar. */
body{display:grid;grid-template-columns:var(--side) minmax(0,1fr);align-items:start}
.side{grid-column:1;grid-row:1;position:sticky;top:0;height:100vh;height:100svh;display:flex;flex-direction:column;gap:40px;padding:30px 18px 30px 22px;border-right:1px solid var(--line);background:var(--paper)}
body > main{grid-column:2;grid-row:1;min-width:0;padding:clamp(12px,3vh,36px) 0 clamp(56px,9vh,96px)}
body > footer{position:fixed;left:0;bottom:0;width:var(--side);padding:0 18px 28px 34px}
footer a{font-size:14px;color:var(--ink-2);text-decoration:none;text-underline-offset:4px}
footer a:hover{color:var(--ink);text-decoration:underline}

/* Lockup: the real mark, the real wordmark in its dark ink (cropped to its ink box: 3523 x 572 inside the 3804 x 880
   brand file; the site's copy is that file at a quarter size, so the same ratios hold), the gallery name under it */
.brand{display:flex;align-items:center;gap:14px;text-decoration:none}
.mark{flex:none;width:46px;height:46px;border-radius:12px;overflow:hidden}
.mark img{display:block;width:100%;height:100%}
.lock{display:flex;flex-direction:column;gap:7px}
.wm{--h:21px;position:relative;display:block;height:var(--h);width:calc(var(--h) * 3523 / 572);overflow:hidden}
.wm img{position:absolute;left:calc(var(--h) * -156 / 572);top:calc(var(--h) * -156 / 572);height:calc(var(--h) * 880 / 572)}
.lock span{font-size:14px;font-weight:480;line-height:1;color:var(--ink-2);white-space:nowrap}
/* The section menu: one row per section, an icon and a name; the current one ("page" on the grid, "true" on a page
   inside it) sits on a light-grey pill. */
.sections ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:4px}
.sections a{display:flex;align-items:center;gap:11px;min-height:42px;padding:0 14px;border-radius:999px;font-size:15px;font-weight:540;color:var(--ink-2);text-decoration:none;transition:background-color .3s var(--ease),color .3s var(--ease)}
.sections a:hover{color:var(--ink);background:var(--card)}
.sections a[aria-current]{color:var(--ink);background:var(--pill)}
.sections a:focus-visible{outline-offset:2px}
.ico{flex:none;display:block}
.count{margin-left:auto;padding-left:4px;font-size:12.5px;font-weight:500;color:var(--ink-2);font-variant-numeric:tabular-nums}

.intro{padding:clamp(28px,6vh,72px) var(--pad) clamp(36px,6vh,64px)}
.intro :is(h1,h2){margin:0;max-width:12.2em;font-weight:540;font-stretch:115%;font-size:clamp(36px,4.3vw,84px);line-height:1;letter-spacing:-.03em;text-wrap:balance}
.intro p{margin:20px 0 0;max-width:62ch;font-size:17px;line-height:1.55;color:var(--ink-2);text-wrap:pretty}

/* The cards: a light-grey rounded frame with a hairline edge, holding a screen that plays the loop; the name and its
   line underneath. */
.grid{list-style:none;margin:0;padding:0 var(--pad);display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:56px 24px}
.card{display:block;text-decoration:none}
.shot{display:block}
.frame{position:relative;display:block;padding:7px;border-radius:18px;background:var(--card);box-shadow:inset 0 0 0 1px var(--line);transition:transform .6s var(--ease),box-shadow .6s var(--ease)}
.frame .face{position:relative;aspect-ratio:16/10;border-radius:11px}
.card:hover .frame,.card:focus-visible .frame{transform:translateY(-4px);box-shadow:inset 0 0 0 1px #d4d4d8}
/* A screen on its own (the copy page's loop) and the parts every screen shares */
.screen{position:relative;display:block;aspect-ratio:16/10}
.face{position:absolute;inset:0;display:block;overflow:hidden;border-radius:10px;background:#e9e9ec;transition:transform .6s var(--ease)}
/* the hairline sits on top: an inset shadow on the face itself would be hidden under the video */
.face::after{content:"";position:absolute;inset:0;border-radius:inherit;box-shadow:inset 0 0 0 1px rgba(15,21,35,.08);pointer-events:none}
.g-tile-video{display:block;width:100%;height:100%;object-fit:cover;border-radius:inherit}
.name{display:block;margin-top:18px;font-size:17px;font-weight:560;letter-spacing:-.005em}
.when{display:block;margin-top:5px;max-width:46ch;font-size:14.5px;line-height:1.5;color:var(--ink-2)}

.close{display:flex;flex-wrap:wrap;align-items:center;gap:18px 28px;margin:clamp(96px,14vh,168px) var(--pad) 0}
.g-cta{display:inline-flex;align-items:center;min-height:54px;padding:0 28px;border-radius:999px;background:var(--ink);color:#fff;font-size:16px;font-weight:580;text-decoration:none;transition:background-color .5s var(--ease),transform .5s var(--ease)}
.g-cta:hover{transform:translateY(-2px);background:#262c3a}
.close p{margin:0;font-size:15.5px;color:var(--ink-2)}

/* The preview (Ivan 10-12; markup in overlay.html, run by gallery.js): an animation opens over the
   gallery on a dark tint the gallery shows faintly through (90%). Under the bar: the live demo on a big
   16:10 screen with the arrows beside it, its line, the button and a pill down to the other animations, all on the first
   screen (gallery.js sizes the screen from the room left). Scrolling darkens the tint to 99% and dims the screen to 13%
   while the other animations come up over it; the bar stays bright. */
/* the gallery stops scrolling while the preview is open; gallery.js pads it by the scrollbar's width so it does not
   shift (a reserved scrollbar gutter instead left a white strip the fixed preview could not cover) */
html.ov-on{overflow:hidden}
.ov{position:fixed;inset:0;z-index:50;color:#fff;color-scheme:dark}
.ov[data-open="0"]{display:none}
.ov-tint{position:fixed;inset:0;background:#000;opacity:var(--ov-tint,.9)}
.ov-scroll{position:absolute;inset:0;overflow-y:auto;overscroll-behavior:contain}
/* the bar is solid, the colour the tint gives the white gallery, so nothing reads through or slides under its words */
.ov-bar{--s:calc(255 * (1 - var(--ov-tint,.9)));position:sticky;top:0;z-index:3;display:flex;align-items:center;gap:12px;height:60px;padding:0 16px 0 20px;background:rgb(var(--s) var(--s) var(--s));box-shadow:0 1px 0 rgba(255,255,255,var(--ov-line,0))}
.ov-home{flex:none;display:block;width:30px;height:30px;border-radius:8px;overflow:hidden}
.ov-home img{display:block;width:100%;height:100%}
.ov-name{margin:0;min-width:0;overflow:hidden;font-size:15.5px;font-weight:560;line-height:1.2;white-space:nowrap;text-overflow:ellipsis}
.ov-tools{display:flex;gap:4px;margin-left:auto}
.ov-tool{display:grid;place-items:center;width:40px;height:40px;padding:0;border:0;border-radius:999px;background:none;color:#fff;cursor:pointer;transition:background-color .3s var(--ease)}
.ov-tool:hover{background:rgba(255,255,255,.12)}
.ov-said{position:absolute;top:54px;right:16px;margin:0;padding:7px 12px;border-radius:9px;background:#26262b;font-size:13.5px}
.ov-said:empty{display:none}
.ov :focus-visible{outline-color:#fff}
.ov-stage{position:relative;z-index:1;display:flex;justify-content:center;align-items:flex-start;gap:36px;padding:4px var(--pad) 18px;opacity:var(--ov-stage,1)}
.ov-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;align-items:center}
.ov-row{display:flex;align-items:center;justify-content:center;gap:20px;width:100%}
.ov .theatre{flex:none;width:var(--ov-w,min(100%,(100vh - 240px) * 1.6))}
.ov .theatre .face{border-radius:16px;background:#141416 var(--poster) center/cover no-repeat}
.ov .face::after{box-shadow:inset 0 0 0 1px rgba(255,255,255,.1)}
.ov-arrow{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:999px;background:rgba(255,255,255,.09);color:#fff;transition:background-color .3s var(--ease)}
.ov-arrow:hover{background:rgba(255,255,255,.18)}
.ov-when{max-width:70ch;margin:16px 0 0;font-size:15px;line-height:1.5;color:rgba(255,255,255,.66);text-align:center;text-wrap:balance}
.ov-actions{display:flex;justify-content:center;margin-top:14px}
/* the button in the brand's blue (the wordmark's dot, deepened so white words keep 5:1) */
.ov .g-cta{min-height:50px;padding:0 26px;background:#2f5fe8}
.ov .g-cta:hover{background:#2852d4}
.ov-more-btn{display:inline-flex;align-items:center;gap:6px;min-height:38px;margin-top:12px;padding:0 14px 0 16px;border-radius:999px;background:rgba(255,255,255,.09);color:#fff;font-size:14.5px;font-weight:540;text-decoration:none;transition:background-color .3s var(--ease)}
.ov-more-btn:hover{background:rgba(255,255,255,.18)}
/* The prompt panel (a member with the key from the Skool card): frosted dark glass on the same tint, so nothing behind
   reads through it, beside the demo on a wide
   screen and under it on a narrower one. Edges of the boxes keep 3:1 against the panel, the hints 6:1. */
.ov-panel{flex:0 0 420px;max-height:calc(100vh - 84px);scroll-margin-top:72px;overflow-y:auto;overscroll-behavior:contain;padding:18px 22px 22px;border-radius:18px;background:rgba(28,28,31,.82);-webkit-backdrop-filter:blur(20px) saturate(1.15);backdrop-filter:blur(20px) saturate(1.15);box-shadow:inset 0 0 0 1px rgba(255,255,255,.1)}
.ov-panel[hidden]{display:none}
.ov-panel-on .ov-arrow{display:none}
.ov-panel-head{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:0 -8px 4px 0}
.ov-panel-title{margin:0;font-size:19px;font-weight:600;letter-spacing:-.005em}
.ov-panel .g-copy-form{gap:16px}
/* Copy prompt stays in view at the panel's foot when a short window makes the panel scroll */
.ov-panel .g-copy-act{position:sticky;bottom:0;z-index:1;margin:0 -22px;padding:14px 22px 14px;background:rgba(30,30,33,.97);box-shadow:0 -1px 0 rgba(255,255,255,.08)}
.ov-cta-open{display:none}
.g-member .ov-cta .ov-cta-locked{display:none}
.g-member .ov-cta .ov-cta-open{display:inline}
.ov-panel .g-copy-how{font-size:15px;color:rgba(255,255,255,.78)}
.ov-panel .g-hint{color:rgba(255,255,255,.62)}
.ov-panel .g-field input{border-color:rgba(255,255,255,.34);background:rgba(255,255,255,.06);color:#fff}
.ov-panel .g-field input:hover{border-color:rgba(255,255,255,.55)}
.ov-panel .g-field input:focus{border-color:#fff}
.ov-panel .g-tool label{border-color:rgba(255,255,255,.34)}
.ov-panel .g-tool label:has(input:checked){background:rgba(255,255,255,.12);border-color:#fff}
.ov-panel .g-tool input{accent-color:#fff}
.ov-panel .g-whole{border-color:rgba(255,255,255,.12)}
.ov-panel .g-whole pre{border-color:rgba(255,255,255,.12);background:rgba(0,0,0,.35);color:rgba(255,255,255,.78)}
@media (max-width:1099px){
  .ov-stage{flex-direction:column;align-items:stretch;gap:24px}
  .ov-panel{flex:none;max-height:none;width:min(100%,560px);align-self:center}
}

/* the other animations, in cells split by hairlines */
.ov-more{position:relative;z-index:2;padding:40px 20px 72px}
.ov-more-title{margin:0 0 18px;font-size:19px;font-weight:560;letter-spacing:-.005em}
.ov-grid{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));border-top:1px solid #232327;border-left:1px solid #232327}
.ov-grid li{padding:18px 18px 16px;background:#060607;border-right:1px solid #232327;border-bottom:1px solid #232327}
.ov .frame{padding:0;background:none;box-shadow:none}
.ov .card:hover .frame,.ov .card:focus-visible .frame{box-shadow:none}
.ov .frame .face{border-radius:10px}
.ov .name{margin-top:13px;font-size:15px}
.ov .when{display:none}
/* The screen is usually a fraction of a pixel wide or tall (1109.02 px), but the demo inside lays out at whole pixels
   (1109), so whatever sits behind the demo showed as a 1px line down the right edge of every light demo. The frame runs
   1px past the screen on the right and the bottom, and the screen's rounded edge clips it. Nothing dark sits behind a
   demo: the frame is clear and the site's copy of each demo has a clear page (tools/gallery-site.mjs), since every
   demo's own section covers its frame. Their dark page colour used to rim the rounded corners of light demos and fill
   the screen black until a demo loaded; the screen shows the demo's poster frame instead. */
.theatre{position:relative;aspect-ratio:16/10}
.g-demo{display:block;width:calc(100% + 1px);height:calc(100% + 1px);border:0;border-radius:inherit;background:transparent}
/* A demo that is taller than the screen in its own layout gets .g-zoom (set by gallery.js): it is then laid out at the
   1280 x 800 its tile was recorded at and scaled down to fit, so nothing is cut off and nothing scrolls inside the frame.
   A demo that fits keeps its own layout, and its pause button stays full size. Phones never zoom: their screen grows
   instead. tan(atan2(a, b)) is a / b as a plain number. Browsers without it (or without cqw) keep the demo's layout. */
@supports (transform:scale(tan(atan2(100cqw,1280px)))){
  .theatre{container-type:inline-size}
  .g-zoom .g-demo{position:absolute;top:0;left:0;width:max(100%,1280px);height:max(100%,800px);transform-origin:0 0;transform:scale(min(1,tan(atan2(100cqw,1280px))))}
}
@media (max-width:1400px){.ov-grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:999px){.ov-arrow{display:none}}
@media (max-width:900px){.ov-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* phones: the screen takes the width and most of the window, and grows when a demo's own phone layout needs more
   (Blueprint needs 772 px at 390 px wide), so every demo shows full size */
@media (max-width:640px){
  .ov-bar{height:56px;padding:0 8px 0 14px}
  .ov-stage{padding:0 12px 16px}
  .ov .theatre{width:100%;aspect-ratio:auto;height:var(--ov-h,calc(100vh - 150px))}
  .ov .theatre .face{border-radius:14px}
  .ov-more{padding:32px 12px 56px}
  .ov-grid{grid-template-columns:1fr}
}

/* three columns of cards on a wide screen, two on a tablet, one on a phone */
@media (max-width:1280px){.grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
/* At 900 px and under the sidebar becomes a top bar: the lockup on the left, the sections as tabs that wrap onto a
   second line rather than scroll or hide, and the footer back at the foot of the page. */
@media (max-width:900px){
  :root{--side:0px}
  body{display:block}
  .side{position:static;height:auto;flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 20px;padding:20px var(--pad);border-right:0;border-bottom:1px solid var(--line);background:none}
  .sections ul{flex-direction:row;flex-wrap:wrap}
  .sections a{min-height:44px;padding:0 14px}
  .count{margin-left:0}
  body > main{padding:8px 0 0}
  body > footer{position:static;width:auto;padding:56px var(--pad) 44px}
}
@media (max-width:720px){.intro p{font-size:16px}}
@media (max-width:640px){.grid{grid-template-columns:1fr;gap:48px}}
@media (max-width:480px){
  .g-cta{width:100%;justify-content:center;text-align:center;min-height:56px;padding:14px 24px;line-height:1.3;text-wrap:balance}
  .side{padding:16px var(--pad)}
  .brand{gap:12px}
  .mark{width:40px;height:40px;border-radius:10px}
  .wm{--h:18px}
  .lock{gap:6px}
  .lock span{font-size:12.5px}
  .sections a{font-size:14px;gap:9px;padding:0 12px}
  .name{margin-top:16px}
}
@media (prefers-reduced-motion:reduce){*{transition:none!important}}

/* ===== Copy page (plan Task 27a): /gallery/prompts/<slug>, opened from the Skool card with the key in the link. =====
   Locked: the name and one line back to the classroom. Open: the loop on the left, the three boxes and Copy prompt on
   the right; on a phone they stack. Everything below belongs to the copy page only. */
.g-opening .g-locked{visibility:hidden}
/* under the top bar, the short locked page still puts the footer at the bottom of the window (the bar and the footer
   are about 220 px); beside the sidebar there is nothing under it to push down */
@media (max-width:900px){.g-copy-page{min-height:calc(100vh - 220px);min-height:calc(100svh - 220px)}}
.g-locked-note{display:flex;flex-direction:column;align-items:flex-start;gap:22px;margin-top:24px}
.g-locked-note p{margin:0}
/* the boxes keep up to 480 px but give the screen room on a laptop: never more than 38% of the row */
.g-copy{display:grid;grid-template-columns:minmax(0,1fr) min(480px,38%);grid-template-areas:"screen head" "screen side";grid-template-rows:auto 1fr;column-gap:clamp(40px,4.5vw,88px);align-items:start;padding:clamp(8px,2vh,24px) var(--pad) 0}
.g-copy-head{grid-area:head}
.g-copy-head h1{margin:0;font-weight:540;font-stretch:115%;font-size:clamp(34px,3.2vw,60px);line-height:1;letter-spacing:-.03em;text-wrap:balance}
.g-copy-head p{margin:14px 0 0;max-width:42ch;font-size:16px;line-height:1.55;color:var(--ink-2)}
/* the screen stays in view while the right side scrolls (the whole prompt is long), and never grows taller than the window */
.g-copy-screen{grid-area:screen;position:sticky;top:24px;max-width:calc((100vh - 140px) * 1.6)}
.g-copy-screen .face{border-radius:14px}
.g-copy-side{grid-area:side;padding-top:30px}
.g-copy-form{display:flex;flex-direction:column;gap:22px}
.g-copy-how{margin:0;font-size:16px;line-height:1.55}
.g-field{display:flex;flex-direction:column}
.g-field label,.g-tool legend{font-size:15.5px;font-weight:560}
.g-hint{margin:4px 0 10px;font-size:14px;line-height:1.45;color:var(--ink-2)}
.g-field input{width:100%;min-height:52px;padding:0 16px;border:1px solid var(--field);border-radius:12px;background:var(--paper);color:var(--ink);font:inherit;font-size:16px;transition:border-color .3s var(--ease)}
.g-field input:hover{border-color:var(--ink-2)}
.g-field input:focus{border-color:var(--ink)}
.g-field input:focus-visible{outline-offset:3px}
.g-tool{margin:0;padding:0;border:0;min-width:0}
.g-tool legend{padding:0;margin-bottom:10px}
.g-tool-opts{display:flex;flex-wrap:wrap;gap:10px}
.g-tool label{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:0 18px;border:1px solid var(--field);border-radius:999px;font-size:15px;font-weight:540;cursor:pointer}
.g-tool label:has(input:checked){background:var(--pill);border-color:var(--ink)}
.g-tool input{margin:0;accent-color:var(--ink)}
/* the focus ring moves from the radio to its whole pill; a browser without :has() keeps the radio's own ring */
@supports selector(:has(*)){
  .g-tool label:has(input:focus-visible){outline:2px solid var(--ink);outline-offset:3px}
  .g-tool input:focus-visible{outline:none}
}
.g-copy-btn{align-self:flex-start;border:0;font-family:inherit;cursor:pointer}
.g-copy-act{display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.g-copy-status{margin:0;min-height:1.55em;font-size:15px}
.g-whole{margin-top:28px;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.g-whole summary{display:flex;align-items:center;justify-content:space-between;min-height:52px;font-size:15.5px;font-weight:560;cursor:pointer;list-style:none}
.g-whole summary::-webkit-details-marker{display:none}
.g-whole summary::after{content:"";width:8px;height:8px;margin-right:6px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:translateY(-3px) rotate(45deg);transition:transform .3s var(--ease)}
.g-whole[open] summary::after{transform:translateY(2px) rotate(-135deg)}
.g-whole pre{margin:0 0 18px;max-height:min(60vh,560px);overflow:auto;padding:16px 18px;border:1px solid var(--line);border-radius:12px;background:var(--card);color:var(--ink-2);font:13px/1.6 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;white-space:pre-wrap;overflow-wrap:anywhere}
.g-whole pre:focus-visible{outline-offset:3px}
.g-live{display:inline-flex;align-items:center;min-height:44px;margin-top:8px;font-size:15.5px;font-weight:540;color:var(--ink-2);text-decoration:none;text-underline-offset:4px}
.g-live:hover{color:var(--ink);text-decoration:underline}
@media (max-width:900px){
  .g-copy{grid-template-columns:minmax(0,1fr);grid-template-areas:"head" "screen" "side";grid-template-rows:none;row-gap:28px}
  .g-copy-screen{position:static;max-width:none}
  .g-copy-side{padding-top:4px}
}
