/* =========================================================================
   Essay Template
   Used by: essays/<slug>/index.html
   Author each essay with just:
     <link rel="stylesheet" href="../shared/template.css">
     <script src="../shared/template.js" defer></script>
     <body>
       <div class="essay">
         <div class="sketch-pane" id="sketchPane"></div>
         <div class="text-pane" id="textPane">
           <article class="prose">
             <section data-sketch="sketches/foo.html"><h1>...</h1><p>...</p></section>
             <section data-sketch=""><p>...</p></section>   <!-- empty = no sketch -->
             ... more sections ...
           </article>
         </div>
       </div>
     </body>
   The text flows as one continuous column that scrolls line-by-line (smoothly,
   but snapping to the line grid so the reading line stays put). Each <section>
   names the sketch shown in the left pane while it is being read; the template
   mounts those sketches and crossfades to the active section's one.
   The template also injects: settings gear, fullscreen icon, swap-panes icon,
   section indicator, settings menu.
   ========================================================================= */

:root {
  --canvas-bg: #f0f0f0;
  --text-bg: #ffffff;
  --text-color: #000000;
  --border-color: rgba(0, 0, 0, 0.13);
  --indicator-color: rgba(0, 0, 0, 0.6);
  --mobile-canvas-height: 45dvh;
}

html,
body {
  height: 100%;
  width: 100%;
  overflow: hidden !important;
}

body {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  /* track the *visible* viewport on mobile (URL-bar aware) */
  position: fixed;
  inset: 0;
  font-family: "Garamond", serif;
  color: var(--text-color);
  background-color: var(--text-bg);
}

/* --- Essay layout -------------------------------------------------------
   Two panes side by side. The left (sketch) pane is fixed and crossfades to
   the sketch tied to whichever section is currently being read. The right
   (text) pane is one continuous, line-scrolled column of prose. */

.essay {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  display: flex;
  overflow: hidden;
}

body.panes-swapped .essay {
  flex-direction: row-reverse;
}

/* --- Sketch pane (left) ------------------------------------------------- */

.sketch-pane {
  width: 50%;
  height: 100vh;
  height: 100dvh;
  box-sizing: border-box;
  overflow: hidden;
  background-color: var(--canvas-bg);
  position: relative;
  flex: 0 0 50%;
}

/* Every section's sketch is mounted once and stacked; only the active one is
   faded in, so switching sections never reloads (and never resets) a sketch. */
.sketch-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.5s ease;
}

.sketch-frame.active {
  opacity: 1;
  visibility: visible;
}

/* Placeholder shown for sections whose interactive sketch isn't built yet. */
.sketch-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8% 12%;
  box-sizing: border-box;
  background-color: var(--canvas-bg);
}

.sketch-placeholder-inner {
  max-width: 22em;
  text-align: center;
  font-family: "Menlo", monospace;
  font-size: 13pt;
  line-height: 1.5;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--indicator-color);
  opacity: 0.55;
}

@media (prefers-reduced-motion: reduce) {
  .sketch-frame {
    transition: none;
  }
}

/* --- Text pane (right) -------------------------------------------------- */

.text-pane {
  width: 50%;
  height: 100vh;
  height: 100dvh;
  box-sizing: border-box;
  overflow-y: auto;
  /* iOS momentum scrolling + allow vertical touch panning of this container. */
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  position: relative;
  background-color: var(--text-bg);
  flex: 0 0 50%;
  /* JS drives scrolling discretely line-by-line; hide the native bar so the
     custom smooth animation reads as the single source of motion. */
  scrollbar-width: none;
}

.text-pane::-webkit-scrollbar {
  width: 0;
  height: 0;
}

.prose {
  padding: 40px;
  /* Trailing space so the final lines can rise to the reading position. */
  padding-bottom: 70vh;
  max-width: 100%;
  box-sizing: border-box;
}

.prose section {
  margin: 0;
}

/* Typography in the text pane */

.prose h1 {
  font-family: "Menlo", monospace;
  font-size: 36pt;
  margin-top: 0;
  line-height: 1.1;
}

.prose h2 {
  font-family: "Menlo", monospace;
  font-size: 24pt;
  line-height: 1.15;
  margin-top: 1.4em;
}

.prose p,
.prose li {
  font-size: 16pt;
  line-height: 1.5;
  overflow-wrap: break-word;
  -moz-hyphens: auto;
  -webkit-hyphens: auto;
  -ms-hyphens: auto;
  hyphens: auto;
  text-align: justify;
  text-justify: inter-word;
}

.prose p {
  margin-bottom: 24px;
}

/* Hidden-message reveal system (triggered via postMessage from iframes) */
.message {
  opacity: 0;
  transition: opacity 2s ease;
}

.message:not([hidden]) {
  opacity: 1;
}

/* --- Floating chrome ---------------------------------------------------- */
/* All chrome buttons share a common minimal-icon style: ~40px square,
   currentColor SVG, semi-transparent, brighter on hover. */

.chrome-icon-btn {
  position: fixed;
  width: 40px;
  height: 40px;
  cursor: pointer;
  background: none;
  border: none;
  padding: 0;
  color: currentColor;
  opacity: 0.35;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: opacity 0.3s ease, transform 0.3s ease;
}

.chrome-icon-btn:hover {
  opacity: 0.85;
}

.chrome-icon-btn svg {
  width: 24px;
  height: 24px;
  color: currentColor;
}

#settingsGear {
  top: 20px;
  right: 20px;
  /* gear glyph is busier than the others, scale up slightly */
}

#settingsGear svg {
  width: 28px;
  height: 28px;
}

#settingsGear.menu-open {
  opacity: 1;
}

#settingsGear.spin {
  animation: spinGear 0.6s ease-in-out;
}

#settingsGear.spin-reverse {
  animation: spinGearReverse 0.6s ease-in-out;
}

@keyframes spinGear {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
}

@keyframes spinGearReverse {
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(-360deg);
  }
}

#fullscreenBtn {
  top: 20px;
  right: 64px;
}

#expandSketchBtn {
  top: 20px;
  right: 108px;
}

body.sketch-expanded .sketch-pane {
  width: 100% !important;
  height: 100vh !important;
  height: 100dvh !important;
  flex: 0 0 100% !important;
}

body.sketch-expanded .text-pane {
  display: none !important;
}

body.sketch-expanded #swapPanesBtn {
  display: none !important;
}

/* Swap-panes icon: anchored on the boundary between the two panes.
   Desktop = vertical boundary (center of viewport).
   Mobile  = horizontal boundary (top of text pane, below canvas). */
#swapPanesBtn {
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

#swapPanesBtn:hover {
  transform: translate(-50%, -50%) scale(1.1);
}

/* --- Slide indicator (floating, bottom-center) ------------------------- */

.slide-indicator {
  position: fixed;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  font-family: "Menlo", monospace;
  font-size: 12px;
  color: var(--text-color);
  opacity: 0.4;
  z-index: 999;
  pointer-events: none;
  letter-spacing: 0.05em;
}

/* --- Settings menu ----------------------------------------------------- */

#settingsMenu {
  position: fixed;
  top: 70px;
  right: 20px;
  background-color: var(--text-bg);
  border: 1px solid var(--border-color);
  border-radius: 3px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  z-index: 999;
  overflow: visible;
  transform-origin: top center;
  transition: opacity 0.3s ease, transform 0.3s ease, visibility 0.3s ease, background-color 0.3s ease;
  opacity: 0;
  transform: scaleY(0);
  pointer-events: none;
  visibility: hidden;
}

#settingsMenu.show {
  opacity: 1;
  transform: scaleY(1);
  pointer-events: auto;
  visibility: visible;
}

.theme-btn,
.color-btn {
  padding: 8px 12px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.2s;
  white-space: nowrap;
  text-align: center;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  color: currentColor;
}

.scroll-btn {
  padding: 8px 12px;
  border: none;
  background: transparent;
  cursor: pointer;
  font-size: 13px;
  transition: all 0.2s;
  white-space: nowrap;
  text-align: center;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  color: currentColor;
}

.theme-btn:hover,
.color-btn:hover,
.scroll-btn:hover {
  background-color: rgba(0, 0, 0, 0.05);
}

.theme-btn.active,
.color-btn.active,
.scroll-btn.active {
  background-color: rgba(0, 0, 0, 0.1);
}

.icon-svg {
  width: 20px;
  height: 20px;
  color: currentColor;
}

.theme-btn-label,
.color-btn-label,
.scroll-btn-label {
  position: absolute;
  right: 100%;
  margin-right: 8px;
  opacity: 0;
  transition: opacity 0.2s;
  pointer-events: none;
  font-weight: 500;
  font-size: 13px;
  white-space: nowrap;
}

.theme-btn:hover .theme-btn-label,
.color-btn:hover .color-btn-label,
.scroll-btn:hover .scroll-btn-label {
  opacity: 1;
}

.menu-separator {
  height: 1px;
  background-color: var(--border-color);
  margin: 4px 0;
}

.color-swatch {
  width: 24px;
  height: 24px;
  border-radius: 3px;
  border: 1px solid rgba(0, 0, 0, 0.2);
}

/* --- Dark mode --------------------------------------------------------- */

body.dark-mode {
  --canvas-bg: #161616;
  --text-bg: #161616;
  --text-color: #ffffff;
  --border-color: rgba(255, 255, 255, 0.13);
  --indicator-color: #aaa;
  background-color: #161616 !important;
}

body.dark-mode .theme-btn:hover,
body.dark-mode .color-btn:hover,
body.dark-mode .scroll-btn:hover {
  background-color: rgba(255, 255, 255, 0.1);
}

body.dark-mode .theme-btn.active,
body.dark-mode .color-btn.active,
body.dark-mode .scroll-btn.active {
  background-color: rgba(255, 255, 255, 0.15);
}

body.dark-mode .color-swatch {
  border-color: rgba(255, 255, 255, 0.4);
}

/* --- Mobile / narrow viewports ---------------------------------------- */

@media (max-width: 900px) {
  .essay {
    flex-direction: column;
  }

  body.panes-swapped .essay {
    flex-direction: column-reverse;
  }

  .sketch-pane {
    width: 100%;
    height: var(--mobile-canvas-height);
    flex: 0 0 var(--mobile-canvas-height);
  }

  .text-pane {
    width: 100%;
    /* Fill the remaining height below the canvas and own the scroll. A zero
       flex-basis with min-height:0 makes the pane reliably bounded (so it
       actually overflows and scrolls) instead of growing to its content. */
    height: auto;
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
  }

  .prose {
    padding: 24px 20px;
    padding-bottom: 70vh;
  }

  .prose h1 {
    font-size: 28pt;
  }

  .prose h2 {
    font-size: 20pt;
  }

  .prose p,
  .prose li {
    font-size: 14pt;
  }

  /* Swap icon sits on the horizontal boundary between canvas and text. */
  #swapPanesBtn {
    top: var(--mobile-canvas-height);
    left: 50%;
    transform: translate(-50%, -50%);
  }

  #swapPanesBtn:hover {
    transform: translate(-50%, -50%) scale(1.1);
  }

  /* Rotate the swap arrows to indicate vertical swap on mobile. */
  #swapPanesBtn svg {
    transform: rotate(90deg);
  }
}