@font-face{font-family:'Diatype Variable';src:url('fonts/jost-latin.woff2?v=1793171601') format('woff2-variations');font-weight:100 900;font-display:swap}
@font-face{font-family:'Optician Sans';src:url('fonts/hanken-grotesk-400.woff2?v=1793171601') format('woff2');font-weight:400;font-display:swap}
@font-face{font-family:'Monument Grotesk Variable';src:url('fonts/jost-latin.woff2?v=1793171601') format('woff2-variations');font-weight:100 900;font-display:swap}

/* ---- Kolin's own theme ---- */
html {
	--mobile-scale: 1.4;
	--mobile-padding-offset: 0.35;
}

body {
	--swatch-1: rgba(0, 0, 0, 0.85);
	--swatch-2: rgba(0, 0, 0, 0.75);
	--swatch-3: rgba(0, 0, 0, 0.6);
	--swatch-4: rgba(0, 0, 0, 0.4);
	--swatch-5: rgba(0, 0, 0, 0.25);
	--swatch-6: #ff0000;
	background-color: rgba(0, 0, 0, 0.04);
}

body.mobile {
}

a:active,
.linked:active,
.zoomable::part(media):active {
	opacity: 0.7;
}

.page a.active {
	color: #ff0000;
}

sub {
	position: relative;
	vertical-align: baseline;
	top: 0.3em;
}

sup {
	position: relative;
	vertical-align: baseline;
	top: -0.4em;
}

.small-caps {
	font-variant: small-caps;
	text-transform: lowercase;
}

ol {
	margin: 0;
	padding: 0 0 0 2.8em;
}

ul {
	margin: 0;
	padding: 0 0 0 2.0em;
}

ul.lineated {
	margin: 0;
	padding: 0;
	list-style-type: none;
	margin: 0 0 0 3em;
	text-indent: -3em;
}

blockquote {
	margin: 0;
	padding: 0 0 0 2em;
}

hr {
	background: rgba(0, 0, 0, 0.1);
	border: 0;
	height: 1px;
	display: block;
	margin-top: 1rem;
	margin-bottom: 1rem;
}

.content {
	border-color: rgba(0,0,0,.85);
}

bodycopy {
	font-size: 1.4rem;
	font-weight: 333;
	color: #000000;
	font-family: "Diatype Variable";
	font-style: normal;
	line-height: 1.2;
	letter-spacing: 0em;
	display: block;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

bodycopy a {
	color: #ef1a3a;
	text-decoration: none;
}

bodycopy a:hover {
}

h1 {
	font-family: "Diatype Variable";
	font-style: normal;
	font-weight: 300;
	margin: 0;
	font-size: 3.2rem;
	line-height: 1.2;
	color: rgba(0, 0, 0, 0.75);
	letter-spacing: 0em;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

.mobile h1 {
	font-size: 3rem;
}

h1 a {
	color: rgba(0, 0, 0, 0.75);
	text-decoration: none;
}

h1 a:hover {
}

h2 {
	font-family: "Diatype Variable";
	font-style: normal;
	font-weight: 300;
	margin: 0;
	color: rgba(0, 0, 0, 0.75);
	font-size: 2.2rem;
	line-height: 1.2;
	letter-spacing: 0em;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

h2 a {
	color: rgba(0, 0, 0, 0.75);
	text-decoration: none;
}

h2 a:hover {
}

.caption {
	font-size: 1.2rem;
	font-weight: 300;
	color: rgba(0, 0, 0, 0.85);
	font-family: "Diatype Variable";
	font-style: normal;
	line-height: 1;
	letter-spacing: 0em;
	display: block;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

.caption a {
	color: rgba(0, 0, 0, 0.85);
	text-decoration: none;
}

.caption a:hover {
}

media-item .caption {
	margin-top: .5em;
}

gallery-grid .caption,
gallery-columnized .caption,
gallery-justify .caption {
	margin-bottom: 2em;
}

[thumbnail-index] .caption {
	text-align: left;
}

[thumbnail-index] .caption .tags {
	margin-top: 0.25em;
}

.page {
	justify-content: flex-end;
	background-color: rgba(0, 0, 0, 0);
}

.page-content {
	padding: 4rem;
	text-align: left;
}

.mobile [id] .page-layout {
	max-width: 100%;
	padding: 0;
}

.mobile [id] .page-content {
	border: 0;
	border-radius: 0;
}

.page-layout {
	align-items: flex-start;
	max-width: 60%;
}

media-item::part(media) {
	border: 0;
	padding: 0rem;
}

.quick-view {
	height: 100%;
	width: 100%;
	padding: 4rem;
	margin-top: auto;
	margin-right: auto;
	margin-bottom: auto;
	margin-left: auto;
}

.quick-view-background {
	background-color: #ffffff;
}

.quick-view .caption {
	color: rgba(255, 255, 255, 1.0);
	padding: 20px 0;
	text-align: center;
	transition: 100ms opacity ease-in-out;
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
}

.quick-view .caption-background {
	padding: 0.5rem 1rem;
	display: inline-block;
	background: rgba(0, 0, 0, 0.5);
	border-radius: .5rem;
	text-align: left;
	max-width: 50rem;
}

.mobile .quick-view {
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 10px;
}

.mobile .quick-view .caption {
	padding: 10px 0;
}

.mobile-menu {
	--text-style: "Mobile menu";
	font-size: 2rem;
	font-weight: 700;
	color: rgba(0, 0, 0, 0.75);
	font-family: "Diatype Variable";
	font-style: normal;
	line-height: 2;
	letter-spacing: 0em;
	display: block;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

.mobile-menu a {
	color: rgba(0, 0, 0, 0.75);
	text-decoration: none;
}

.mobile-menu a:hover {
	
}

.small {
	--text-style: "small";
	font-size: 1.2rem;
	font-weight: 333;
	color: rgba(0, 0, 0, 0.5);
	font-family: "Diatype Variable";
	font-style: normal;
	line-height: 1.3;
	letter-spacing: 0em;
	display: block;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

.small a {
	color: rgba(0, 0, 0, 0.8);
	text-decoration: none;
}

.small a:hover {
	
}

.desk-menu {
	--text-style: "Desk menu";
	font-size: 1.3rem;
	font-weight: 300;
	color: rgba(0, 0, 0, 0.75);
	font-family: "Diatype Variable";
	font-style: normal;
	line-height: 1.5;
	letter-spacing: 0em;
	display: inline-block;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
}

.mobile .desk-menu {
	font-size: 1.8rem;
}

.desk-menu a {
	color: #000000;
	text-decoration: none;
}

.mobile .desk-menu a {
	color: rgba(0, 0, 0, 0.75);
}

.desk-menu a:hover {
	
}

.news {
	--text-style: "News";
	font-size: 2.2rem;
	font-weight: 400;
	color: #000000;
	font-family: "Optician Sans";
	font-style: normal;
	line-height: 1;
	letter-spacing: 0;
	display: inline-block;
	filter: drop-shadow(0.2rem 0.2rem 0rem rgba(0,0,0,0.25));
	will-change: filter;
}

.news a {
	color: #000000;
	text-decoration: none;
}

.news a:hover {
	
}

.mobile .quick-view .caption-background {
	max-width: 100vw;
}

::part(slideshow-nav) {
	--button-size: 30px;
	--button-inset: 20px;
	--button-icon-color: rgba(255, 255, 255, 0.9);
	--button-icon-stroke-width: 1.5px;
	--button-icon-stroke-linecap: none;
	--button-background-color: rgba(87, 87, 87, 0.35);
	--button-background-radius: 50%;
	--button-active-opacity: 0.7;
}

gallery-slideshow::part(slideshow-nav) {
	--button-inset: 15px;
}

.quick-view::part(slideshow-nav) {
}

.wallpaper-slideshow::part(slideshow-nav) {
}

.mobile ::part(slideshow-nav) {
	--button-inset: 10px;
}

.mobile .quick-view::part(slideshow-nav) {
	--button-inset: 25px;
}

shop-product {
	font-size: 1.2rem;
	max-width: 22rem;
	font-family: "Diatype Variable";
	font-style: normal;
	font-weight: 400;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
	letter-spacing: 0em;
	margin-bottom: 1em;
}

shop-product::part(price) {
	color: rgba(0, 0, 0, 0.75);
	line-height: 1.1;
	margin-bottom: 0.5em;
}

shop-product::part(dropdown) {
	width: 100%;
	color: rgba(0, 0, 0, 0.85);
	border: 1px solid rgba(0, 0, 0, 0.2);
	background-color: rgba(255, 255, 255, 0.0);
	background-image: url(https://static.cargo.site/assets/images/select-line-arrows.svg);
	background-repeat: no-repeat;
	background-position: top 0em right .1em;
	line-height: 1.2;
	padding: 0.58em 2em 0.55em 0.9em;
	border-radius: 10em;
	margin-bottom: 0.5em;
}

shop-product::part(button) {
	background: rgba(0, 0, 0, 0.15);
	color: rgba(0, 0, 0, 0.75);
	text-align: left;
	line-height: normal;
	padding: 0.5em 1em;
	cursor: pointer;
	border-radius: 10em;
}

shop-product::part(button):active {
	opacity: .7;
}

audio-player {
	--text-color: rgba(0, 0, 0, 0.85);
	--text-padding: 0 1.2em 0 1.0em;
	--background-color: rgba(255, 255, 255, 0);
	--buffer-background-color: rgba(0, 0, 0, 0.03);
	--progress-background-color: rgba(0, 0, 0, 0.075);
	--border-lines: 1px solid rgba(0, 0, 0, 0.2);
	font-size: 1.2rem;
	width: 32rem;
	height: 2.75em;
	font-family: "Diatype Variable";
	font-style: normal;
	font-weight: 400;
	font-variation-settings: 'slnt' 0, 'MONO' 0;
	line-height: normal;
	letter-spacing: 0em;
	margin-bottom: 0.5em;
	border-radius: 10em;
}

audio-player::part(button) {
	--icon-color: rgba(0, 0, 0, 0.85);
	--icon-size: 32%;
	--play-text: '';
	--pause-text: '';
	width: 3.15em;
	display: inline-flex;
	justify-content: center;
	cursor: pointer;
}

audio-player::part(play-icon) {
	padding-left: 0.6em;
}

audio-player::part(pause-icon) {
	padding-left: 0.4em;
}

audio-player::part(progress-indicator) {
	border-right: 1px solid rgba(0, 0, 0, 0);
	height: 100%;
	cursor: ew-resize;
}

audio-player::part(separator) {
	border-right: var(--border-lines);
}

body.mobile audio-player {
	max-width: 100%;
}

.mobile .content {
	border: 0;
	margin: 0;
}
/* ---- engine (overrides) ---- */
:root{--viewport-height:100vh}
/* ===== arch layout engine: verbatim Cargo DOM behaviour ===== */
*{box-sizing:border-box}
/* --- engine root size: WIDTH-ONLY (user decision 2026-10-16) ---
   User's ideal = the live 4K (3840x2160) view, measured there: root 31.104px
   (= min(w,h)*0.0144 at 16:9). Rule: root = width * 0.0081, capped at
   31.104px — sizing depends ONLY on window width (changing height changes
   nothing), scales up to 4K, and freezes beyond 4K. All rem-based sizes
   (menu text, 2-col gallery tracks, 39.38rem rows) follow width accordingly.
   Earlier min(vw,vh)-based model made the page bigger on tall windows and
   smaller on short ones — the exact behaviour the user rejected in his
   vertical-window-changing note (2026-10-16). */
   html{font-size:clamp(10.02px, min(100vw * 0.0081, 31.104px), 31.104px)}
html,body{min-height:100vh;margin:0;padding:0}
body{background:rgba(0,0,0,0.04);color:#000;font-family:"Diatype Variable","Jost",sans-serif;
  display:flex;flex-direction:column;width:100%;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:none}
a{color:inherit;text-decoration:none}
/* --- page tree (Cargo DOM: .content > pinned page + .pages) --- */
.content{display:flex;flex-direction:column;align-items:flex-start;justify-content:flex-start;
  min-height:100%;position:relative;flex-grow:1;border-color:transparent;border-width:0;width:100%}
.pages{width:100%;flex:1 0 auto}
.page{position:relative;isolation:isolate;display:flex;justify-content:flex-end;
  width:100%;min-height:var(--viewport-height, 100vh);flex:0 1 100%}
.page-layout{flex-grow:1;position:relative;display:flex;flex-direction:row;align-items:flex-start;
  justify-content:flex-start;width:0%;max-width:60%}
.page-content{display:flex;flex-direction:row;height:100%;align-items:flex-start;
  border-color:transparent;border-width:0;width:100%;position:relative;isolation:isolate}
bodycopy{display:block;contain:layout;word-wrap:break-word;position:relative;max-width:100%;width:100%}
/* --- pinned nav (live: position:fixed top/left, z-index 2, 23% width via local_css) --- */
.page.pinned{position:fixed;top:0;left:0;z-index:2;pointer-events:none}
.page.pinned .page-content{pointer-events:auto}
/* --- body media (media-item stand-in) --- */
.mi{position:relative;display:flex;overflow:hidden;max-width:100%}
/* NOTE 2026-10-15: .mi had an invented background:rgba(0,0,0,.03) (first pilot,
   commit 04d72db). Live media-item background is transparent — the 3% shade sat
   BEHIND the transparent nav logo and showed as a near-white plate (4% page +
   3% frame = 93% white). Removed -> logo floats directly on the page background. */
/* live media-item in the nav is display:inline-flex (vertical-align bottom):
   it flows inline inside the <a>, so the following <br> lines sit exactly where
   live has them. Block display pushed the nav 19px down. */
.page.pinned .mi{display:inline-flex;vertical-align:bottom}
.mi img{display:block;width:100%;height:100%;object-fit:fill}
.mi-missing{display:inline-block;padding:.6rem .8rem;background:rgba(255,0,0,.12);color:#a00;
  font-size:.9rem;border:1px dashed #a00;margin:.4rem 0}
/* --- gallery-grid / authored .gallery: live-measured grid model (2026-10-13) ---
   Live: rows of FIXED cells, zero gaps, rows overflow the text column on narrow
   windows (verified: 2-col row pitch 282.4px = 21.79rem; 1-col pitch 510.4px +
   caption → 39.38rem). Caption sits INSIDE the grid item; .mi flex-fills the
   rest so the pitch matches live regardless of caption metrics. */
gallery-grid,.gallery{display:grid;width:100%;overflow:visible;margin:0;gap:0}
.gallery-grid.cols-1,.gallery.cols-1{grid-template-columns:minmax(0,82.08rem);grid-auto-rows:39.38rem}
.gallery-grid.cols-1 .tile,.gallery.cols-1 .tile{height:39.38rem}
/* home (page content) 1-col gallery: NO fixed row — each tile is the photo at
   its natural aspect (the 1200x514 thumbnails are all 2.33:1) + caption below
   it, so the photo never stretches. WIDTH-ONLY sizing (user decision
   2026-10-16, ideal = live 4K 3840x2160 where the home photo measured
   2696px = 70.21vw): on desktop the tile width is 70.21vw capped at 2696px
   (= the ideal's own width at 4K; keeps the photo at native sharpness — the
   thumbnails are 2560-3400px, so 2696 never upscales them past their own
   resolution by more than an invisible ~5%). Changing window HEIGHT changes
   nothing; mobile (<=860) keeps full-width photos via the 1fr rule below. */
.gallery.cols-1.dyn{grid-auto-rows:auto}
.gallery.cols-1.dyn .tile{height:auto}
.gallery.cols-1.dyn .mi img{height:auto !important}
@media(min-width:861px){
  .gallery.cols-1.dyn{grid-template-columns:min(70.21vw, 2696px)}
}
.gallery-grid.cols-2,.gallery.cols-2{grid-template-columns:repeat(2,40.94rem);grid-auto-rows:21.79rem}
.gallery-grid.cols-2 .tile,.gallery.cols-2 .tile{height:21.79rem}
.gallery-grid.cols-4,.gallery.cols-4{grid-template-columns:repeat(4,20.46rem)}
/* --- project GRID PAGES: the grid view the dot/dots toggle jumps to.
   Model fixed 2026-10-17 after Kolin's live screenshot proof: the live
   engine sizes columns by REM (20.91rem = the same measure as the old
   4-col gallery rule) with a 1rem gutter. Verified pixel-true from the
   user's own live screenshot (window ~1870x1020, root 15.55px): 4
   columns 324px wide (=20.91rem) + 16px gutters (=1rem), rows = tallest
   photo's natural height at that width, tiles top-aligned in their row.
   Earlier CDP tile reads (271px fixed, 0 gap) were UNPAINTED placeholder
   boxes — live lazy media don't paint under CDP, and the placeholder
   geometry is not the final layout (pixel truth beat the DOM probe).
   Clicking a tile opens the quick-view zoom (live behaviour). */
.ggrid{display:grid;gap:1rem}
/* --- one-page view toggle (2026-10-19: slideshow + grid on ONE page) ---
   Each project page carries both views: the slideshow block (default) and
   a .gvs-sec section per gallery holding the grid page's own gallery block
   (same column-set wrapper -> the same stack-gap margins in either view,
   decisions #16/#17). The dot/dots icons toggle .view-grid on bodycopy;
   state persists across reloads (history state, pushed by the toggle
   script). The standalone <slug>-grid page remains for no-JS. */
.gvs-sec{display:none}
bodycopy.view-grid gallery-slideshow,
bodycopy.view-grid .qv{display:none}
bodycopy.view-grid .gvs-sec{display:block}
/* UNIFORM grid wall: equal FLUID columns (1fr) fill the text column
   edge-to-edge, rows size to their TALLEST photo (exact ratios); a short
   last row keeps its smaller tiles (normal grid behaviour - no brick
   scale-to-fill, Kolin 2026-10-24). The only thing that steps is the
   COLUMN COUNT: the inline fit-script on each grid page rewrites the
   template with the window-width ladder (the shared Brick-gallery-
   stepping ladder: top 1000+N*100 px, N-3 equal pixel bands down to 600
   px, 2 on phones - count only ever steps down). Fixed n here is the
   no-JS fallback for the wide start. */
.ggrid.c4{grid-template-columns:repeat(4,1fr)}
.ggrid.c3{grid-template-columns:repeat(3,1fr)}
.ggrid.c2{grid-template-columns:repeat(2,1fr)}
.ggrid .gcell{display:flex;align-items:center;justify-content:flex-start;cursor:zoom-in}
.ggrid .gcell .mi{width:100%;flex:0 0 auto}
.ggrid .gcell:hover .mi{opacity:.85}
/* --- bricks (gallery-justify strips, 2026-10-23 pilot: interior-layouts) ---
   Rows are flex rows; the no-JS bake sets each row's height via
   aspect-ratio (a fraction of the container width) and each tile's
   width + gutter as PERCENTS (the layout is width-self-similar at a
   fixed N; see the bricks notes in build_arch.py). The resize script
   re-packs in px (N ladder 4->3->2). Tiles never crop: the .mi fills a
   box that already IS the photo's exact ratio. */
.bricks{display:block;width:100%}
.br-row{display:flex;flex-shrink:0;align-items:stretch;justify-content:flex-start;flex-wrap:nowrap;max-width:100%}
.br-row .brk{position:relative;display:flex;flex:0 0 auto;max-width:100%;cursor:zoom-in}
.br-row .brk:hover{opacity:.85}
.br-row .brk .mi{max-width:none}
.br-row.orphan-row{display:inline-flex;width:auto}
.br-row .brk .mi img{object-fit:fill}
.gallery .tile{display:flex;flex-direction:column;align-items:stretch}
/* media box flex-fills; caption (block-level, margins from theme) rides below it */
.gallery .mi{flex:1 1 auto;min-height:0;aspect-ratio:auto;max-width:none}
/* captions (from verbatim theme: .5em top on media; 2em bottom in grids) */
.media-item .caption,.mi~.caption,.tile .caption{margin-top:.5em}
gallery-grid .caption,.gallery .caption{margin-bottom:2em}
.gallery .tile:hover{opacity:.85}
.gallery .mi-empty{background:rgba(0,0,0,.06)}
/* --- slideshow (project pages): live slideshow engine (rebuilt 2026-10-16) ---
   Live behaviour (measured on arch.kolindin.com 2026-10-16):
   - slide width = column width (993px @1440); the CURRENT photo sits
   - UNIFIED ADAPTIVE HEIGHT (Kolin request 2026-10-27, same rule as the
     rebuilt art home hero): one height for EVERY slide in the track, decided
     by syncH: h = min(what the window leaves below the frame, 57rem, and
     the height the WIDEST photo still fits at its exact ratio inside the
     column). Every photo is then drawn at exactly that height — narrower
     ones shrink in width instead of cropping. The box never morphs
     and always fits the window (resize re-runs syncH). Width transitions
     removed: the stuck-transition quirk (see zoom note below) made morphing
     unreliable and it is no longer wanted. */
   - AUTOPLAY (user-confirmed): auto-advances every ~3s (Cargo default
     autoplay-delay; shadow-studies page stores a faster override) and
     pauses while the pointer is over the photo (pause-on-hover=true);
     manual clicks restart the clock;
   - arrows: 30px circle, 15px inset from the frame edge, vertically centred,
     bg rgba(87,87,87,.35), white chevron stroke 1.5px butt caps — the site
     theme's own ::part(slideshow-nav) tokens (::part is inert for our plain
     markup, so these are written out explicitly here);
   - arrows visible ON HOVER ONLY (--navigation-opacity 0 when idle). */
gallery-slideshow{position:relative;width:100%}
.ss-frame{position:relative;overflow:clip}
.ss-track{display:flex;overflow:visible;transition:transform .5s cubic-bezier(.24,0,.29,1);will-change:transform}
.ss-slide{flex:0 0 100%;width:100%;height:100%;align-self:stretch;display:flex;justify-content:flex-start;align-items:center}
.ss-slide .mi{background:none;width:100%;cursor:zoom-in}
.ss-slide .mi img{aspect-ratio:auto!important;max-height:none!important;object-fit:fill}
.ss-arrow{position:absolute;top:50%;transform:translateY(-50%);z-index:6;width:30px;height:30px;padding:0;
  border:0;border-radius:50%;background:rgba(87,87,87,.35);cursor:pointer;opacity:0;transition:opacity .15s ease-in-out}
.ss-prev{left:15px}.ss-next{right:15px}
.ss-arrow svg{display:block;width:100%;height:100%}
.ss-arrow svg path{fill:none;stroke:rgba(255,255,255,.9);stroke-width:1.5px;stroke-linecap:butt}
.ss-arrow:hover,.ss-arrow:focus-visible{background:rgba(87,87,87,.5)}
.ss-arrow:hover svg path{stroke:rgba(255,255,255,1)}
gallery-slideshow:hover .ss-arrow, gallery-slideshow:focus-within .ss-arrow{opacity:1}
/* --- zoom view (the live site's quick-view, measured on rawene-2-0 2026-10-17) ---
   Live facts: full-viewport fixed overlay, z 5001, background #ffffff, padding
   3rem (32.7974px at root 10.9325), photo centered at its EXACT natural ratio
   (contain-fit, never cropped — measured 1233x694 for a 3000x1687 source in a
   1520x759 window: height-limited); buttons are the same 30px circles as the
   slideshow arrows with --button-inset:25px (measured); close circle 20px from
   top/right (pixel-located 1470-1499 x 20-50 in a 1520 window); Escape closes
   (clicking the background/photo does NOT close — verified). */
.qv{position:fixed;top:0;left:0;right:0;bottom:0;z-index:5001;background:#fff;opacity:0;pointer-events:none;transition:opacity .2s ease}
.qv.qv-open{opacity:1;pointer-events:auto}
.qv-stage{position:absolute;top:0;left:0;right:0;bottom:0;overflow:hidden}
/* the CLIP sits exactly at the framed content area (viewport minus the
   3rem frame) — clipping at the stage box lets neighbor slides leak
   into the margin (visible as side strips in tall windows, 2026-10-17
   user report). Static box (no transform), so no paint-kill risk. */
.qv-clip{position:absolute;top:4rem;left:4rem;right:4rem;bottom:4rem;overflow:hidden}
.qv-track{position:absolute;top:0;left:0;right:0;bottom:0;display:flex;overflow:visible;transition:transform .5s cubic-bezier(.24,0,.29,1);will-change:transform}
.qv-slide{flex:0 0 100%;width:100%;display:flex;align-items:center;justify-content:center}
.qv-slide .mi{background:none;width:100%;min-width:0;flex:0 0 auto;transition:none}
/* ZOOM widths apply instantly: the inherited `transition:width .5s` (the
   slideshow morph) can get STUCK at its start value when the change lands
   while the layer is not painted yet — 1:1 photos then rendered full-track
   width and got cropped top+bottom (caught measuring 2026-10-18; verified
   stuck >2s, no !important involved, fresh-DOM control resolves correctly).
   The slideshow track no longer morphs at all (unified height, 2026-10-27),
   so its width transition was removed too. */
.qv-slide .ss-slide{height:100%}
/* ZOOM photos are CENTRED (live quick-view measured 2026-10-17: contain in
   the padded viewport). The SLIDESHOW track stays left-aligned (shrink-to-
   fit, user decision 2026-10-17) — that left-align must not leak into the
   zoom: it made narrow/tall photos swing left with a sliver of the next
   photo at the right edge (Kolin screenshot, grid zoom, 2026-10-17). */
.qv-slide .ss-slide{align-items:center;justify-content:center}
.qv-slide .mi img{aspect-ratio:auto!important;max-height:none!important;object-fit:fill;display:block}
.qb{position:fixed;top:50%;transform:translateY(-50%);z-index:6;width:30px;height:30px;padding:0;
  border:0;border-radius:50%;background:rgba(87,87,87,.35);cursor:pointer}
.qb svg{display:block;width:100%;height:100%}
.qb svg path{fill:none;stroke:rgba(255,255,255,.9);stroke-width:1.5px;stroke-linecap:butt}
.qb:hover{background:rgba(87,87,87,.5)}
.qb:hover svg path{stroke:rgba(255,255,255,1)}
.qc{top:20px;right:20px;transform:none}
.qqb{left:25px}.qnb{right:25px}
@media(max-width:860px){.qv-clip{top:10px;left:10px;right:10px;bottom:10px}.qc{top:10px;right:10px}.qqb{left:10px}.qnb{right:10px}}
/* --- column-set (live behavior verified 2026-10-15 @1440x900) ---
   unspanned column-units are EQUAL (488/488, 326/325/326 measured);
   spanned units proportional to span (span 7 / span 5 = 570/407);
   no gutter deduction from the widths. (Old rule — last child grows to
   fill — was wrong: it starved unspanned columns and crushed the info
   page badge image to 0px.) */
column-set{display:flex;flex-direction:row;align-items:flex-start;width:100%}
column-unit{display:block;word-wrap:break-word;position:relative;max-width:100%;flex:1 1 0;min-width:0}
column-unit[span="3"]{flex:3 1 0}column-unit[span="5"]{flex:5 1 0}
column-unit[span="6"]{flex:6 1 0}column-unit[span="7"]{flex:7 1 0}
/* column-set HORIZONTAL gutter (decision #44 spacing law, Kolin approved
   2026-10-28): neighbouring column UNITS get one shared 4rem gap — same rule
   as the art site. The old Cargo-default 1rem and authored 2rem rows are
   normalised into the ladder. (History: the 2026-10-21 audit matched the live
   engine's 1rem default; superseded by #44.) mobile-stack resets it below. */
column-set:has(>column-unit~column-unit)>column-unit:not(:last-child){margin-right:4rem}
/* contact block (AKL/NZ / arch@kolindin.com / kolindin.com) — authored <small>,
   drawn AT FULL BODYCOPY SIZE on live (measured 2026-10-21 @1922x952: 19.19px =
   exactly 1.4rem, same as live bodycopy). The browser's built-in <small> shrink
   (≈0.83x) made it ~16% smaller locally — that is Kolin's "text is too small". */
bodycopy small{font-size:inherit}
/* --- text --- */
/* icon glyphs: live engine sizes every text-icon at 1.2em of its context
   (measured 2026-10-17 on rawene live: toggle icons 20.2px = 1.2 x 1.4rem;
   menu arrows 20.21px = 1.2 x 1.3rem). Our 1em read ~30% smaller — user
   flagged the project-page view toggles specifically. */
.icon{width:1.2em;height:1.2em;fill:currentColor;vertical-align:-0.15em;margin-right:.1em}
/* view-toggle links (rawene's dot/dots pair): live has NO font-size override —
   they inherit the bodycopy size (1.4rem), glyph = 1.2em → 1.68rem icon
   (measured 21.76px @ root 12.96). Our 1.2rem override read smaller. */
.icon-link{display:inline-block;margin-right:.4rem}
/* unified toggle block (decision #44 ladder + icon-gap fix, Kolin confirmed
   2026-10-28): dot/dots pair sits in a flex row with EQUAL breathing room
   above and below: 1rem from the window top and 1rem down to the gallery.
   The two glyphs sit EXACTLY 1rem apart — the stray Cargo &nbsp; is stripped
   at build (it became a third flex item and stretched the gap to 3.44rem)
   and the .icon-link margin does not apply inside the toggle row.
   Phones keep the !important 1.5rem/6.2rem bar clearance. */
.view-toggle{display:flex;gap:1rem;line-height:1;margin-bottom:1rem}
.view-toggle .icon-link,.view-toggle .icon{margin-right:0}
.view-toggle .icon{display:block}
/* decision #47 (Kolin 2026-10-28): hover law for EVERY site - the INACTIVE
   toggle icon turns accent red on hover (art behaviour); the active icon
   stays black even under the cursor. Active view = solid glyph (#18/#32),
   now carried by the .active class instead of Cargo's inline colors. */
.view-toggle .icon-link{color:rgb(171,171,171)}
.view-toggle .icon-link:hover{color:#ef1a3a}
.view-toggle .icon-link.active{color:#000}
.page-content:has(bodycopy .view-toggle){padding-top:1rem}
/* b/strong: live uses the engine default `bolder`, landing at 400 over the
   333-weight body text (measured 2026-10-15); our 600 read as bold. */
b,strong{font-weight:bolder}
a:active,.linked:active{opacity:.7}
sub{position:relative;vertical-align:baseline;top:.3em}
sup{position:relative;vertical-align:baseline;top:-.4em}
/* mobile */
@media(max-width:860px){
  /* Cargo base-unit formula, calibrated to live (320→10.02 360→11.29 390→12.23 430→13.48 px) */
  html{font-size:clamp(10.02px, calc(10.02px + (100vw - 320px) * 0.031476), 13.801px)}
  /* desktop pinned rail disappears */
  .content>.page.pinned{display:none}
  /* single full-width column (desktop local css must not leak through) */
  .content{min-height:0;padding:0}
  .page{display:block;width:100%;min-height:100%}
  .page .page-layout{max-width:none!important;width:100%;justify-content:flex-start!important;align-items:stretch}
  .page .page-content{padding:1.5rem!important;max-width:100%}
  /* full-width media (override inline scale boxes) */
  .mi,.mi img{max-width:100%}
  gallery-slideshow .mi{max-width:100%!important;height:auto!important;aspect-ratio:auto!important;max-height:none}
  /* columns stack */
  column-set{flex-wrap:wrap}column-unit{flex:1 1 100%!important;max-width:100%!important}
  /* stacked mobile: row gutters become vertical gaps (decision #44:
     stacked blocks keep the 4rem block-to-block gap) */
  column-set>column-unit:not(:last-child){margin-right:0!important}
  column-set>column-unit:not(:last-child){margin-bottom:4rem}
  .gallery{display:grid;grid-template-columns:1fr!important;gap:0!important}
  .gallery .tile{width:100%!important;max-width:100%}
  .gallery .mi{height:auto!important;aspect-ratio:auto!important;max-width:100%}
  .gallery .mi img{object-fit:cover;object-position:center}
  /* grid pages on phones: TWO columns filling the width (Kolin 2026-10-18:
     "the mobile view should has two colums, not one") — each column is
     fluid (1fr), so the 2-up adapts to any portrait width, photos keep
     their exact ratios. This is the NO-JS phone fallback: with JS, the
     fit-script's ladder count wins (its inline important out-ranks this
     rule) — the ladder already shows 2 below 600px (and 3 between 600
     and 760).
     !important: the desktop .ggrid.c4{repeat(4,1fr)} has higher specificity
     (0,2,0); a media query adds none — the earlier mobile column overrides
     silently never applied (caught 2026-10-18).
     Live mobile = 4 fixed columns overflowing the phone (broken) — not a
     reference (Kolin 2026-10-17: "the gaps are ok for now" — spacing as
     shipped stands). */
@media(max-width:760px){
  .ggrid{grid-template-columns:repeat(2,1fr) !important}
}
  /* pinned top title bar + bottom arrows (measured: 60px / 50px @root 12.23) */
  .mobile-top{position:fixed;top:0;left:0;right:0;z-index:400;background:#f6f6f6;height:4.9rem}
  .mobile-top .mt-bar{height:100%;max-width:none;padding:0 1.4rem;display:flex;align-items:center;gap:.8rem}
  .mobile-top h2{margin:0;font-size:2.2rem;font-weight:300;color:rgba(0,0,0,.75);line-height:1;white-space:nowrap;overflow:hidden}
  .mobile-top h2 b{font-weight:600}
  .mobile-top .mt-logo{margin-left:auto}
  .mobile-top .mt-logo img{height:2.7rem;width:auto;object-fit:contain;display:block}
  .mobile-bottom{position:fixed;bottom:0;left:0;right:0;z-index:400;background:rgba(255,255,255,.94);
    display:flex;justify-content:center;gap:1.6rem;height:3.6rem;align-items:center;padding:0}
  .mobile-bottom .icon-link{color:rgba(0,0,0,.3);font-size:1.96rem;font-weight:300;text-decoration:none;
    margin:0;display:inline-flex}
  /* keep content away from the pinned bars (needs !important: the 1.5rem
     !important padding above beats plain specificity — 2026-10-15 user
     screenshot showed the first photo's top hidden under the mobile top bar) */
  .content .page .page-content:first-child{padding-top:6.2rem !important}
}
/* mobile menu page (nav-mobile) — list view */
.mobile-menu-page .menu-inner{padding:6.2rem 1.4rem 1.2rem}
.mobile-menu-page .menu-link{display:block;font-size:2rem;font-weight:700;
  color:rgba(0,0,0,.75);line-height:2.82;margin:0;text-decoration:none}
.mobile-menu-page .menu-link .icon{font-size:1em}
.mobile-menu-page .menu-sect{display:block;font-size:1.4rem;font-weight:333;color:rgb(239,26,58);
  margin:1.2rem 0 .2rem;text-decoration:none}
.mobile-menu-page hr{background:rgba(0,0,0,.1);border:0;height:1px;margin:1.2rem 0}
.mobile-menu-page .caption{font-size:1.2rem;font-weight:300;color:rgba(0,0,0,.85);margin:0;padding:0}
.mobile-menu-page .menu-inverse{font-size:.9em;vertical-align:baseline;color:rgba(0,0,0,.6)}
@media(max-width:860px){
  .mobile-menu-page{position:static;min-height:100vh;z-index:500;background:rgba(0,0,0,.1)}
}
@media(min-width:861px){
  .mobile-top,.mobile-bottom{display:none}
  .mobile-menu-page{max-width:40%;margin:0 auto;min-height:100vh;background:rgba(0,0,0,.1);position:static}
}
