/* =====================================================================
   Sebastian Cole Galvan — pan & zoom gallery
   World units: 1 world unit = 1 CSS px at zoom scale 1.
   World geometry (keep in sync with panzoom.js):
     WORLD_W = 24000 | column: x 10000..14000, y 6000..6000+colH
   ===================================================================== */
* { margin: 0; padding: 0; box-sizing: border-box; }
:root { --fs: 1.21; } /* font scale: 2 sizes up */
@media (max-width: 820px) { :root { --fs: 1.46; } } /* phone: 4 sizes up */
html.large-text { --fs: 1.77; } /* large text: 4 font sizes bigger than the desktop default */
@media (max-width: 820px) { html.large-text { --fs: 2.14; } } /* phone large text: 4 sizes bigger than the phone default */
/* large-text overlap guards: the few fixed-px rules that must keep pace with the scaled fonts.
   The divisors equal the default scale, so non-large rendering is pixel-identical. */
html.large-text .wip { height: calc(231px * var(--fs)); } /* the WIP lines' container grows with the text */
html.large-text .wip .m { top: calc(111px * var(--fs)); } /* second WIP row stays below the first instead of overlapping */
html.large-text .howto { margin-top: calc(380px * var(--fs) / 1.21); } /* phone header gap keeps pace */
html, body {
  width: 100%; height: 100%; overflow: hidden; background: #000;
  overscroll-behavior: none; touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
body {
  font-family: Arial, Helvetica, sans-serif; user-select: none;
  cursor: url("../images/cursor-open.png") 15 24, auto;
}
body.dragging { cursor: url("../images/cursor-closed.png") 11 17, auto; }
img { display: block; -webkit-user-drag: none; user-select: none; }

/* ---- world & backgrounds ---- */
#world {
  position: absolute; left: 0; top: 0;
  width: 24000px; height: 60000px;             /* JS refines height */
  transform-origin: 0 0; will-change: transform;
}
#bg-gradient {
  position: absolute; left: 0; top: 0; width: 24000px; height: 100%; z-index: 0;
  /* sampled from blueprint: TL cyan -> TR magenta -> BL orange -> BR yellow */
  background: linear-gradient(135deg, #00aeee 0%, #a723b1 19%, #e71684 39%,
              #e79140 61%, #fecc12 69%, #fef100 100%);
}
#bg-tile {
  position: absolute; left: 6000px; top: 0; width: 12000px; height: 100%; z-index: 1;
  background: url("../images/tile.jpg") repeat; background-size: 2000px 1000px;
}
#floaters { position: absolute; left: 0; top: 0; width: 0; height: 0; z-index: 6; pointer-events: none; }
#floaters > * { position: absolute; left: 0; top: 0; will-change: transform; }
#floaters img, #floaters video { width: 100%; height: auto; }

/* ---- central column ---- */
#column { position: absolute; left: 10000px; top: 6000px; width: 4000px; z-index: 3; }
.block { width: 100%; background: #000; position: relative; z-index: 2; }

/* ---- header 1 : name ---- */
.header-block { padding: 220px 130px 150px; }
.site-name {
  display: flex; justify-content: space-between;
  font-size: calc(188px * var(--fs)); line-height: 1; color: #fff; font-weight: bold; letter-spacing: 4px;
}
.star { color: #ffe14f !important; font-style: normal; }
.wip { position: relative; height: 280px; margin-top: 15px; font-weight: bold; font-size: calc(134px * var(--fs)); line-height: 1; }
.wip span { position: absolute; }
.wip .b { color: #3aa0ff; top: 0; }
.wip .m { color: #ff2fa0; top: 134px; }
.howto { margin-top: 130px; color: #fff; font-size: calc(50px * var(--fs)); line-height: 1.7; }

/* ---- movement assist toggle ---- */
.assist-toggle {
  display: inline-block; position: relative;
  margin-left: 21em; /* 1.5x the previous 14em offset */
  margin-top: 0.4em;
  color: #fff; /* same size/style as the instruction text */
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
  -webkit-user-select: none;
}
/* forgiving hit area (same zoom-compensating halo as the read/img toggles) */
.assist-toggle::after {
  content: ''; position: absolute;
  left: calc(-40px * var(--hs, 1)); right: calc(-20px * var(--hs, 1));
  top: calc(-18px * var(--hs, 1)); bottom: calc(-18px * var(--hs, 1));
}
.assist-toggle input {
  transform: scale(2.8); /* twice the previous 1.4 */
  vertical-align: middle;
  margin-right: 0.5em;
  accent-color: #fff;
  cursor: pointer;
}

/* hand-ui controls (toggles + bio square): pointer fist on hover, click fist while pressed */
.hand-ui {
  cursor: url("../images/pointer%20fist.png") 10 4, pointer;
}
.hand-ui:active {
  cursor: url("../images/click%20fist.png") 12 12, pointer;
}

/* the email address sits beside the bio toggle on the SAME line, same style but blue (no halo: not clickable) */
.assist-toggle.email {
  margin-left: 0.5em;
  color: #3aa0ff;
  cursor: default;
}
.assist-toggle.email::after { content: none; }

/* ---- virtual fist cursors (touch devices; one per finger) ---- */
.virtual-cursor {
  position: fixed;
  left: -200px;
  top: -200px;
  height: 32px;      /* matches the OS cursor render size (browsers clamp cursors to 32px) */
  width: auto;
  pointer-events: none;
  z-index: 9999;
  opacity: 0;
  transform: translate(-50%, -50%);
  will-change: opacity;
}
.virtual-cursor.show { opacity: 1; transition: opacity 120ms; }
.virtual-cursor.fade { opacity: 0; transition: opacity 3s ease-out; }
.virtual-cursor.fade2 { opacity: 0; transition: opacity 2s ease-out; }   /* wheel-trackpad fists: 2s fade */

/* ---- dividers ---- */
.divider-thin {
  height: 20px;   /* thinner still (36 -> 27 -> 20 per request) */
  background: linear-gradient(90deg, #2020ff, #00b4ff, #00e070, #c8e600, #ffc800, #ff7300, #ff2020);
}
.divider-big {
  position: relative; height: 700px;
  background: linear-gradient(90deg, #2020ff, #00b4ff, #00e070, #c8e600, #ffc800, #ff7300, #ff2020);
}
/* ---- section 1 : CGI filmstrip ---- */
/* filmstrip is wider than the column and bleeds into the tiled world on both sides */
.sec1 { padding: 340px 0 20px; } /* bottom slimmed so the text block sits centered between photos and section end */
.sec1 .filmstrip {
  background: #fff; display: flex; justify-content: center; gap: 10px; padding: 8.5px 0; /* +5px total height */
  width: max-content; position: relative; left: 50%; transform: translateX(-50%);
}
.filmstrip img { height: 1190px; width: auto; }
.sec1-text { padding: 180px 400px 160px; color: #fff; } /* 180 above = 160 text + 20 section below, centered */
.sec1-text h2 { font-size: calc(52px * var(--fs)); font-style: italic; display: inline; margin-right: 90px; }
.sec1-text .meta { font-size: calc(38px * var(--fs)); font-weight: bold; }
.sec1-text .body { font-size: calc(32px * var(--fs)); line-height: 1.55; text-align: left; max-width: 3200px; margin-top: 44px; }

/* ---- section 2 : poem ---- */
.sec2 { display: flex; gap: 150px; padding: 340px 200px; align-items: stretch; }
.poem-img { width: 1250px; flex: none; height: auto; }
.poem-text {
  color: #fff; font-style: italic; font-size: calc(38px * var(--fs)); line-height: 1.5;
  display: flex; flex-direction: column; justify-content: space-between;
}
.poem-text p { max-width: 1750px; }
/* desktop stanza nudges: 1 line = calc(57px * var(--fs)); the negative bottom
   margin cancels the shift so later stanzas and the caption stay put */
.poem-text p:nth-child(1) { margin-top: calc(285px * var(--fs)); margin-bottom: calc(-285px * var(--fs)); } /* stanza 1 down 5 lines (3 + 2 more per request) */
.poem-text p:nth-child(2) { margin-top: calc(228px * var(--fs)); margin-bottom: calc(-228px * var(--fs)); } /* stanza 2 down 4 lines */
/* right column of the duo starts 4 lines lower: "I the ripple".."I the chemistry"
   lines up with "you the pebble".."you sweat" instead of "at an unfathomable distance".."you the pebble" */
.poem-text .duo span + span { margin-top: calc(228px * var(--fs)); }
.poem-text .duo { display: flex; gap: 96px; max-width: none; align-items: flex-start; } /* flex-start: columns keep natural height so the offset lines them up cleanly */
.poem-text .duo span { white-space: nowrap; } /* the longest line sets the span width exactly; a device rendering it 1px wider would wrap and shift the whole column, breaking the 4-line pairing ("I the ripple" landing beside "And me" instead of "You the pebble"). Lines are far narrower than the 4000px column, so nowrap is always safe. */
.poem-text p:last-child { margin-top: calc(-57px * var(--fs)); } /* last stanza up 1 line (desktop) */
.poem-text .caption { font-style: normal; font-weight: bold; margin-top: 40px; margin-bottom: 0; }

/* ---- sections 3-5 : artwork ---- */
.sec { padding: 340px 160px; }
.sec img { width: 100%; height: auto; }
.sec3 .fish-row { display: flex; justify-content: center; align-items: flex-end; margin: 400px 0; gap: 0; } /* pushed down: top margin was 130px */
.sec3 .fish-row img { width: 19%; }   /* 50% of the previous 38%, edges touching */
.sec3 .fish-wide { width: 64%; margin: 0 auto; }
.sec4 img { width: 76%; margin: 0 auto; }
.sec5 img { width: 92%; margin: 0 auto; }

/* both titles VERTICAL, stacked side by side with the "&" between them
   (feedback: one vertical + one horizontal read wrong) */
.secbaro { padding: 340px 160px 280px; }
.baro-row { display: flex; gap: 60px; align-items: flex-end; }
.baro-vert {
  flex: none; width: max-content; white-space: nowrap; /* ONE vertical line, no wrapping */
  margin-bottom: calc(-180px * var(--fs)); /* whole text block sits 2 lines lower */
  color: #fff; font-style: italic; font-size: calc(64px * var(--fs));
  writing-mode: vertical-rl; transform: rotate(180deg); /* reads bottom-to-top */
}
.baro-amp {
  flex: none; width: max-content; font-size: calc(64px * var(--fs)); font-weight: bold;
  margin-bottom: calc(-180px * var(--fs)); /* starts level with the two titles' start */
  color: #fff; writing-mode: vertical-rl; transform: rotate(180deg);
}
.baro-line {
  flex: none; width: max-content; white-space: nowrap; /* one vertical line */
  margin-bottom: calc(-180px * var(--fs));
  color: #fff; font-style: italic; font-size: calc(60px * var(--fs));
  writing-mode: vertical-rl; transform: rotate(180deg); /* reads bottom-to-top, starts level with the title */
}
.baro-row img { flex: 1; min-width: 0; height: auto; align-self: center; }
.baro-bottom {
  margin-top: calc(180px * var(--fs)); /* keeps the 2-line-lower relationship */
  color: #fff;
}
.baro-line b { font-style: normal; font-weight: bold; font-size: 1.3em; }
.baro-meta { font-weight: bold; font-size: calc(38px * var(--fs)); }
.secstatement { background: #000; padding: 440px 360px; }
.secstatement h2 { color: #fff; font-size: calc(82px * var(--fs)); font-weight: bold; margin-bottom: 140px; }
.secstatement p { color: #fff; font-size: calc(40px * var(--fs)); line-height: 1.6; max-width: 2900px; margin: 0 auto 120px; padding-left: 480px; }
.secstatement p:last-child { margin-bottom: 0; }
.secflydraw .fly-main { width: 56%; margin: 0 auto; }
.secflydraw .fly-wide { width: 92%; margin: 400px auto 0; } /* shifted down: was 150px */

/* ---- header 2 : finished works ---- */
.header2 { padding: 80px 110px 160px; }
.work-nav { display: flex; justify-content: space-between; font-size: calc(42px * var(--fs)); color: #fff; }
.work-nav .y { color: #ffe14f; }
.works-title {
  display: flex; justify-content: space-between; width: 72%; margin-top: 180px;
  font-size: calc(188px * var(--fs)); color: #3aa0ff; font-weight: bold; letter-spacing: 2px;
}
.works-years {
  display: flex; justify-content: space-between; width: 76%; margin-top: 15px;
  font-size: calc(148px * var(--fs)); color: #ff2fa0; font-weight: bold;
}
.header2 .divider-thin { margin: 70px -110px 0; }

/* ---- artwork captions (sections 3, 4, 5) ---- */
.art-caption { color: #fff; padding: 260px 160px; } /* equal top/bottom: text centered vertically in the black gap */
.sec3 .art-caption { padding-top: 5px; } /* Pink Face caption 3 lines total higher; shortens the section */
.secflydraw .art-caption, .sec4 .art-caption, .sec5 .art-caption { padding-top: 345px; } /* flydraw + jazz/guts captions one line lower */
.art-caption .cap-head { font-size: calc(52px * var(--fs)); }
.art-caption .cap-head .cap-title { font-style: italic; font-weight: normal; display: inline; }
.art-caption .cap-head .cap-meta { font-weight: bold; font-size: calc(40px * var(--fs)); margin-left: 90px; }
.art-caption .cap-body { font-size: calc(34px * var(--fs)); line-height: 1.55; margin-top: 50px; max-width: 3600px; }

/* ---- section nav widget (screen-fixed, created by panzoom.js, NOT inside #world
   so it never pans/zooms). Press the toggle button to show the up/down arrows,
   press an arrow to snap to the prev/next section, press the toggle to hide.
   Drop your images in assets/images/: nav-widget.png, nav-up.png, nav-down.png —
   until then the buttons render as bordered black squares. ---- */
.nav-widget {
  position: fixed; right: 45px; bottom: 30px; z-index: 50; /* 1.5x the previous 30px */
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.nav-btn {
  width: 45px; height: 45px;             /* 50% of the previous 90px */
  border: none; background-color: transparent; /* no border, no background */
  background-repeat: no-repeat; background-position: center; background-size: contain;
}
.nav-toggle      { background-image: url("../images/widget.png"); }
.nav-toggle:active { background-image: url("../images/widget_click.png"); }
.nav-up          { background-image: url("../images/up_base.png"); }
.nav-up:active   { background-image: url("../images/up_click.png"); }
.nav-down        { background-image: url("../images/down_base.png"); }
.nav-down:active { background-image: url("../images/down_click.png"); }
.nav-widget .nav-btn:not(.nav-toggle) { display: none; }   /* arrows hidden until opened */
.nav-widget { display: none; }   /* TEMP: widget hidden pending redesign — delete this line to bring it back */
.nav-widget.open  .nav-btn { display: block; }             /* widget pressed: show arrows */
/* ---- experimental reading mode (created by panzoom.js). Each section carries
   a small "read" checkbox+label (styled like the assist-toggles); checking it
   opens a black overlay with that section's text re-flowed for reading.
   The toggle lives inside its section, so it pans/zooms with it (it isn't a
   screen-fixed floating button). ---- */
.read-toggle {
  display: inline-flex; align-items: center; gap: 0.65em;   /* visible space between square and label, scales with font size */
  color: #a855f7; white-space: nowrap;   /* read/img labels only — purple */
  cursor: pointer; user-select: none; -webkit-user-select: none;
  margin-top: 1.5em; margin-right: 3em;   /* one full line below the text above */
}
/* forgiving hit area: invisible padding around the toggle lets clicks slightly
   off the visible box still register — appearance unchanged. Extra room on the
   left (the side users tend to undershoot when aiming at the square).
   --hs (set by panzoom.js) is 1/current-zoom, so the halo stays the same size
   on screen at any zoom level (world px shrink as you zoom out; halo grows to
   compensate). */
.read-toggle::after {
  content: ''; position: absolute;
  left: calc(-45px * var(--hs, 1)); right: calc(-25px * var(--hs, 1));
  top: calc(-22px * var(--hs, 1)); bottom: calc(-22px * var(--hs, 1));
}
.read-toggle { position: relative; }
.read-toggle + .read-toggle { margin-left: 1.2em; } /* tighter gap so both sit snugly together */
.read-toggle input {
  transform: scale(2.8);            /* matches the other assist-toggles' square */
  margin: 0; vertical-align: middle; accent-color: #fff; cursor: pointer;
}
.read-toggle + .read-toggle { margin-left: 3em; } /* "IMG." sits to the right of "read" */
/* match the "read" label size to the text it sits under (it's a sibling of the
   big paragraph, so it needs an explicit size rather than inheriting a small one) */
.sec1-text .read-toggle      { font-size: calc(43px * var(--fs)); }
.sec2 .read-toggle           { font-size: calc(51px * var(--fs)); }
.secbaro .read-toggle        { font-size: calc(51px * var(--fs)); }
.secstatement .read-toggle   { font-size: calc(53px * var(--fs)); }
.art-caption .read-toggle    { font-size: calc(45px * var(--fs)); }
.read-overlay {
  display: none; position: fixed; left: 0; top: 0; right: 0; bottom: 0; z-index: 100;
  background: #000; overflow-y: auto; -webkit-overflow-scrolling: touch;
  touch-action: pan-y;   /* allow touch-drag scrolling inside the overlay (html/body are touch-action:none) */
}
.read-overlay.open { display: block; }
.read-close {
  position: fixed; top: 24px; right: 24px; z-index: 101;
  padding: 10px 26px; border: 2px solid #fff; background: #000; color: #fff;
  font-size: 18px; border-radius: 6px;
}
.read-page {
  max-width: 68ch; margin: 0 auto; padding: 96px 28px 120px;
  color: #fff; font-size: 22px; line-height: 1.8; text-align: left;
}
.read-page.wide { max-width: 136ch; } /* statement prose: double the standard measure */
.read-page h2 { font-style: italic; display: inline; margin-right: 24px; }
.read-page .meta { font-weight: bold; }
.read-page .body { margin-top: 32px; }
/* neutralize section layouts inside the reading view so only readable text shows.
   The section (and all its nested text blocks) is forced to adopt .read-page's own
   comfortable sizing — otherwise the clone drags its wide max-widths/large fonts in. */
.read-page .filmstrip, .read-page img, .read-page video, .read-page .read-toggle { display: none; }
.read-page .block, .read-page section, .read-page header, .read-page div {
  padding: 0 !important; margin: 0 !important; width: auto; background: none;
}
.read-page p { padding: 0 !important; }  /* worlds set padding on p (e.g. .secstatement p {padding-left:480px}); must clear so text stays in-column */
.read-page h1, .read-page h2, .read-page h3, .read-page p, .read-page span,
.read-page .cap-head, .read-page .cap-body, .read-page .body, .read-page .meta,
.read-page .baro-vert, .read-page .baro-bottom, .read-page .baro-line,
.read-page .poem-text {
  font-size: inherit !important; line-height: inherit !important;
  max-width: none !important; margin-left: 0 !important;
}
/* baro in the reading view: the two title lines and the medium line become
   separate blocks in the centered reading column (text left-aligned, like the
   rest of the read view — NOT center-aligned). The world title is
   nowrap/vertical — neutralized so it wraps normally. The "&" keeps its
   place between the two titles. */
.read-page .baro-row { display: block; }
/* statement read-view: collapse the big world gaps (120px between paras /
   140px under the title) to a single blank line each */
.read-page .secstatement h2 { margin: 0 0 1em !important; }
.read-page .secstatement p { margin: 0 0 1em !important; }
.read-page .secstatement p:last-child { margin-bottom: 0 !important; }
.read-page .baro-vert {
  writing-mode: initial; transform: none; display: block;
  white-space: normal; flex: initial; width: auto;
  margin: 0 0 20px !important; font-weight: bold;
}
.read-page .baro-amp { display: block; margin: 0 0 12px !important; font-weight: bold; }
.read-page .baro-bottom { display: block; margin: 0 !important; }
.read-page .baro-bottom .baro-line { display: block; margin: 0 0 12px !important; font-style: italic; }
.read-page .baro-bottom .baro-meta { display: block; margin: 0 !important; font-weight: bold; }
/* poem in the reading view: neutralize the in-world stanza nudges — they're
   sized for the big world text, and their negative margins overlap stanzas
   badly at reading scale */
.read-page .poem-text { display: block; }
.read-page .poem-text p { margin: 0 0 1.4em !important; }
.read-page .poem-text .caption { margin-bottom: 0 !important; }
/* duo stays two side-by-side columns; right column offset 4 lines so
   "I the ripple" lines up with "you the pebble" at reading scale */
.read-page .poem-text .duo { display: flex; gap: 2.4em; align-items: flex-start; }
.read-page .poem-text .duo span { display: block; margin: 0 !important; white-space: nowrap; } /* nowrap: same device-font-metric guard as the world poem - one wrapped line would shift the whole column and break the 4-line pairing */
.read-page .poem-text .duo span + span { margin-top: 7.2em !important; }
/* phone overlay: keep the poem at the same 19px as the rest of the overlay (no
   more two font sizes). Side-by-side at 19px needs ~410px but the column is only
   ~335px, so the right column slides LEFT into the whitespace beside the short
   paired lines: "you the pebble".."you sweat" are <=127px wide at 19px (only the
   unpaired lines above/below the pairing band are wide). left:10em puts the
   right column's widest line (124px) ending at ~333px, right before the ~355px
   column edge, while every line stays on one line.
   top:5.6em = 4 lines keeps
   "you the pebble"<gap>"I the ripple" .. "you sweat"<gap>"I the chemistry". */
@media (max-width: 820px) {
  .read-page .poem-text .duo { position: relative; display: block; font-size: 19px !important; line-height: 1.4 !important; }
  .read-page .poem-text .duo span + span { position: absolute; left: 10em; top: 5.6em; margin: 0 !important; }
}
/* image mode: full-width artwork stacked in a vertical row, centered */
.read-page.img-mode { max-width: 1100px; padding: 60px 24px 100px; }
.read-page.img-mode .read-img {
  display: block; width: 100%; height: auto; margin: 0 auto 40px;
  object-fit: contain; background: #000;
}
@media (max-width: 820px) {
  .read-page { font-size: 19px; padding: 72px 20px 96px; }
  .read-page.wide { max-width: 100%; }            /* statement column limited to the phone viewport so it can't overflow and push text off-screen */
  .nav-btn { width: 32px; height: 32px; } /* 50% of the previous 64px */
  .nav-widget { right: 0; }               /* flush against the right edge on phones */
  .howto { margin-top: 380px; }           /* a couple of extra lines after the 2026 line */
  .poem-text p:nth-child(-n+4) {          /* phone: all 4 stanzas down 2 lines, everything else in place */
    margin-top: calc(114px * var(--fs));
    margin-bottom: calc(-114px * var(--fs));
  }
}
