/* ================== Reset ================== */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

/* Prevent a visible light<->dark transition during initial page load.
   script.js removes this class on the next animation frame. */
html.no-theme-transition *,
html.no-theme-transition {
  transition: none !important;
}

/* ================== Root Variables ================== */
:root {
  /* Colors & Fonts */
  --primary-color: black;
  --highlight: black;
  --rootfont: 'Noto Sans', sans-serif;
  --rootfont2: 'Open Sans', sans-serif;
  --rootfont3: 'Noto Serif HK', serif;

  /* Unified UI scaling (square menu, scroll circles, triangle toggle) */
  --ui-scale: 1;

  /* Transition */
  --transition-speed: 5s;
  /* Theme transition used for quick UI color changes (overrides the long page transition) */
  --theme-transition: 3s;

  /* Menu open/close transition (kept separate from global transitions) */
  --menu-transition-speed: 2s;

  /* Floating scrollbar & toggle sizing/offsets (single source of truth) */
  /* single source horizontal offset for UI controls (distance from right edge)
    use --ui-right to position the scroll circle; the toggle is placed to the left
    of the circle using a calc() expression so you only need to change --ui-right */
  /* Unified UI edge spacing (single source of truth for top/left/right offsets)
     If you want a different left padding than right/top, change layout rules,
     not these variables. */
  --ui-offset: 100px;
  --ui-right: var(--ui-offset);
  --ui-left: var(--ui-offset);
  /* Unified top offset (same source as left/right) */
  --ui-top: var(--ui-offset);
  /* Unified bottom offset (used by the triangle toggle wrapper).
    Keep it tied to --ui-offset so changing one knob moves the triangle too. */
  --ui-bottom: var(--ui-offset);

  /* Title tweak */
  --title-top: 0px; /* relative offset for title inside header */
  --scroll-circle-right: 100px; /* legacy alias, kept for compatibility */
  /* Base sizes (do not use directly in layout; use the scaled vars below) */
  --scroll-circle-size-base: 80px;
  --menu-scroll-size-base: 34px;
  --toggle-triangle-base-base: 80px;

  /* Scaled sizes (single knobs: change --ui-scale) */
  --scroll-circle-size: calc(var(--scroll-circle-size-base) * var(--ui-scale));  /* diameter of the scroll circle */
  --toggle-gap: 12px;         /* horizontal gap between circle and toggle */

  /* Header / toggle colors (use variables so they can transition smoothly) */
  --header-text: black;      /* color for title, toggle text, hamburger bars */
  --header-stroke: white;    /* outline/stroke color used in text-shadow */

  /* Scroll circle background */
  --scroll-circle-bg: black;

  /* Unified stroke/outline/border */
  --stroke-thickness: 3px;

  /* Toggle vertical line */
  --toggle-line-width: 6px;
  --toggle-line-height: 70px;
  --toggle-circle-size: 50px;

  /* Hamburger menu */
  --hamburger-line-height: 4px;
  --hamburger-line-spacing: 2px;

  /* Title text stroke */
  --text-stroke-thickness: 2px;

  /* Title sizing (scale with --ui-scale so it responds to media queries) */
  --title-font-size-base: 2rem;
  --title-font-size: calc(var(--title-font-size-base) * var(--ui-scale));
  /* Triangle toggle sizing: change only --toggle-triangle-base to scale the triangle
     (base = width of triangle's base). Height is computed using sqrt(3)/2 * base. */
  --toggle-triangle-base: calc(var(--toggle-triangle-base-base) * var(--ui-scale)); /* default base width */
  --toggle-triangle-half: calc(var(--toggle-triangle-base) / 2);
  --toggle-triangle-height: calc(var(--toggle-triangle-base) * 0.8660254);
  /* Vertical gap between header and the top of the scroll-circle center
     (use this to control the minimum top spacing for the circle). */
  --scroll-circle-top-gap: 75px;
  /* Menu scroll circle (smaller, sits slightly left of main circle) */
  --menu-scroll-size: calc(var(--menu-scroll-size-base) * var(--ui-scale));
  --menu-scroll-gap: 12px; /* horizontal gap from main circle */
  /* Width of the menu overlay when open (percentage of viewport). */
  --menu-overlay-width: 100%;

  /* Menu top padding (space reserved for header controls) */
  --menu-top-padding: 150px;

  /* Unified page padding (used by overlay menu grid + scroll pages)
     Keep this as a single knob per breakpoint for consistent spacing. */
  --page-pad: 20px;
}

/* ================== Base / Scrollbar ================== */
html {
  width: 100%;      /* full viewport width, including scrollbar */
  /* Don't force an always-on scrollbar. It can create an extra/phantom scroll
     layer on some platforms when combined with hidden scrollbar styling. */
  overflow-y: auto;
  scrollbar-gutter: stable both-edges;
  scroll-behavior: smooth;
  /* Hide native scrollbars (we'll show a custom circular indicator) */
  scrollbar-width: none; /* Firefox */
}

html::-webkit-scrollbar {
  width: 0; /* WebKit: hide */
  height: 0;
}

/* Ensure the injected header stays fixed to the viewport even if something
   else on the page is transformed. */
#site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100000;
  transform: none;
}

#site-header * {
  transform: none;
}

/* Floating circular scrollbar indicator */

.custom-scroll-circle {
  position: fixed;
  right: var(--ui-right);
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  border-radius: 50%;
  background: var(--scroll-circle-bg);
  /* above the menu overlay */
  z-index: 100001;
  transform: translateY(-50%);
  pointer-events: auto; /* allow dragging */
  cursor: grab;
  box-shadow: none;
  transition: background var(--theme-transition) ease, opacity 200ms ease, transform 120ms linear;
  opacity: 1;

  /* Dragging should never create text selections/caret. */
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

.custom-scroll-circle:active {
  cursor: grabbing;
}

/* Smaller circular scrollbar used only when the menu overlay is open.
   It is positioned slightly left of the main page scroll-circle so they appear
   as a grouped pair. Hidden by default (opacity 0) and shown when menu opens. */
.menu-scroll-circle {
  position: fixed;
  /* Default to center-to-center alignment with the main page scroll circle.
     (When the menu is closed, this stays hidden via opacity: 0.) */
  right: calc(var(--ui-right) + (var(--scroll-circle-size) - var(--menu-scroll-size)) / 2);
  width: var(--menu-scroll-size);
  height: var(--menu-scroll-size);
  border-radius: 50%;
  background: var(--scroll-circle-bg);
  /* above the menu overlay */
  z-index: 100001;
  transform: translateY(-50%);
  pointer-events: auto;
  cursor: grab;
  box-shadow: none;
  transition: background var(--theme-transition) ease, opacity 160ms ease, transform 120ms linear;
  opacity: 0; /* hidden until menu opens */

  /* Dragging should never create text selections/caret. */
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

/* While dragging either scroll circle, disable text selection/caret globally to prevent flicker. */
body.is-dragging-scroll {
  user-select: none;
  -webkit-user-select: none;
  caret-color: transparent;
}

/* UI labels: positioned by JS using measured element centers for exact alignment. */
.ui-label {
  position: fixed;
  z-index: 100002; /* above scroll circles + menu overlay */
  right: calc(var(--ui-right) + var(--scroll-circle-size) + 12px);
  transform: translateY(-50%);
  font-family: inherit;
  font-weight: 700;
  font-size: calc(var(--scroll-circle-size) * 0.9);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--header-text);
  opacity: 0.85;
  pointer-events: none;
  transition: opacity 200ms ease;
}

/* Optional: fade labels a bit when menu is open (keeps focus on overlay). */
body.menu-open .ui-label {
  opacity: 0.75;
}

/* Entry page: show UI labels briefly on page entry.
   Timeline:
   - 0s..1s: fully transparent
   - 1s..~?: fade to visible
   - 4s..5s: fade back to transparent
*/
body.entry-intro .ui-label {
  opacity: 0;
}

body.entry-intro-labels-in .ui-label {
  opacity: 0.85;
  transition: opacity 600ms ease;
}

body.entry-intro-labels-out .ui-label {
  opacity: 0;
  transition: opacity 1000ms ease;
}

/* Track line behind the menu-scroll-circle (shown only when menu is open). */
.menu-scroll-track {
  position: fixed;
  right: calc(var(--ui-right) + (var(--scroll-circle-size) / 2));
  width: 2px;
  background: var(--scroll-circle-bg);
  opacity: 0;
  z-index: 100000;
  transform: translateX(-50%);
  pointer-events: none;
}

/* When the menu is open, show the menu scroll circle fully opaque */
body.menu-open .menu-scroll-circle {
  opacity: 1;
}
body.menu-open .menu-scroll-track {
  opacity: 0;
}
.menu-scroll-circle:active { cursor: grabbing; }

/* ================== Body ================== */
body {
  font-family: "Helvetica Neue", Arial, sans-serif;
  background: white;
  color: black;
  transition: background var(--transition-speed) ease, color var(--transition-speed) ease;
  /* allow normal scrolling; previously set to hidden which can cause jumpy/discrete scrolling */
  overflow: auto;
  padding-top: 160px;
  margin: 0;

}

/* When the overlay menu is open, prevent the underlying page from scrolling.
   JS adds/removes this class on <body>. */
body.menu-open {
  overflow: hidden;
}

body.dark-mode,
html.dark-mode body {
  background: black;
  color: white;
  /* Dark-mode overrides for theme-aware UI elements */
  --header-text: white;
  --header-stroke: black;
  --scroll-circle-bg: white;
}

/* Ensure overlay close 'X' remains visible in dark mode even if the
   element is rendered outside the usual themed container. */
html.dark-mode .dynamic-overlay-close line,
body.dark-mode .dynamic-overlay-close line {
  stroke: white;
}

/* ================== Entry Page Intro Animation ==================
   Goal: On entry.html, show only the title + UI controls for the first 2s,
   then fade in the project tiles/media over 2s.
   Controlled by JS adding these classes to <body>.
*/
body.entry-intro .project {
  opacity: 0;
  pointer-events: none;
}

body.entry-intro-ready .project {
  opacity: 1;
  pointer-events: auto;
  transition: opacity 2000ms ease;
}

/* ================== Header ================== */
header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 140px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--ui-left);
  z-index: 100000;
  background: none;
}

/* Position the toggle wrapper fixed at the bottom-right of the viewport */
.toggle-wrapper {
  position: fixed;
  right: var(--ui-right);
  left: auto;
  bottom: calc(var(--ui-bottom) + 5px);
  top: auto;
  transform: none;
  z-index: 100001;
  display: flex;
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}

/* Bottom-left overlay launcher (mirrors the triangle toggle size/offset) */
.dynamic-overlay-wrapper {
  position: fixed;
  left: var(--ui-left);
  right: auto;
  bottom: calc(var(--ui-bottom) + 5px);
  top: auto;
  transform: none;
  z-index: 100001;
  display: flex;
  width: calc(var(--scroll-circle-size) * 1.25);
  height: calc(var(--scroll-circle-size) * 1.25);
  align-items: center;
  justify-content: center;
  pointer-events: auto;
}

.dynamic-overlay-btn {
  width: calc(var(--scroll-circle-size) * 1.25);
  height: calc(var(--scroll-circle-size) * 1.25);
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.dynamic-overlay-btn svg {
  width: calc(var(--scroll-circle-size) * 1.25 * 0.84);
  height: calc(var(--scroll-circle-size) * 1.25 * 0.84);
	  overflow: visible;
}

.dynamic-overlay-btn path {
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  transition: stroke var(--theme-transition) ease;
}

.dynamic-overlay-btn .spiral-outline {
  stroke: var(--header-stroke);
  stroke-width: calc(var(--stroke-thickness) * 2.6);
}

.dynamic-overlay-btn .spiral-inner {
  stroke: var(--header-text);
  stroke-width: calc(var(--stroke-thickness) * 1.5);
}

.dynamic-overlay-btn:focus-visible {
  outline: var(--stroke-thickness) solid var(--header-text);
  outline-offset: 4px;
}

/* Full-viewport overlay host (iframe) */
.dynamic-overlay-host {
  position: fixed;
  inset: 0;
  z-index: 200000;
  pointer-events: auto;
}

.dynamic-overlay-host[hidden] {
  display: none !important;
}

.dynamic-overlay-iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  background: transparent;
}

/* Parent-level close (X) shown during launch + while overlay is open */
.dynamic-overlay-close {
    box-sizing: border-box;
    font-size: initial;
  position: fixed;
  left: var(--ui-left);
  right: auto;
  bottom: calc(var(--ui-bottom));
  top: auto;
  transform: none;
  z-index: 100001;
  display: flex;
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  align-items: center;
  justify-content: center;
  pointer-events: auto;
  padding: 0;
  border: none;
  background: transparent;
  cursor: pointer;
}

.dynamic-overlay-close svg {
  width: 100%;
  height: 100%;
  display: block;
  overflow: visible;
}

.dynamic-overlay-close line {
  stroke: var(--header-text);
  stroke-width: calc(var(--stroke-thickness) * 4);
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  transition: stroke 0.3s;
}

/* Strong dark-mode override placed after the default rule so it cannot
   be clobbered by later variable changes. Use high specificity and
   !important to guarantee visibility in dark themes. */
html.dark-mode .dynamic-overlay-close line,
body.dark-mode .dynamic-overlay-close line {
  stroke: white !important;
}

.dynamic-overlay-close:focus-visible {
  outline: 2px solid var(--header-text);
  outline-offset: 4px;
}

/* 3-circle burst emitted after spiral arrival */
.dynamic-overlay-burst-circle {
  position: fixed;
  left: 0;
  top: 0;
  width: 0;
  height: 0;
  border-radius: 50%;
  border: var(--stroke-thickness) solid var(--header-text);
  background: transparent;
  pointer-events: none;
  z-index: 200001;
  box-sizing: border-box;
}

html.dynamic-overlay-open {
  overflow: hidden;
}

body.dark-mode header {
  background: none;
}

/* Support theme class being applied on <html> (pre-paint bootstrap) */
html.dark-mode body.dark-mode header,
html.dark-mode body header {
  background: none;
}

/* ================== Scroll-based Project Scaling (Container) ================== */
.project {
  /* Scroll-based scaling targets the whole tile again (image + overlay).
     Keep this container transformable for the original effect. */
  will-change: transform;
}

/* When JS scales `.project`, keep transform origin stable for media. */
.project img,
.project video {
  transform-origin: center center;
}

/* ================== Title ================== */

.title {
  position: absolute;
  z-index: 100002; /* above .menu (99999) and header (100000) */
  left: var(--ui-left);
  top: calc(var(--ui-top) + var(--title-top));
  /* Keep the wrapper centered on its anchor, but allow JS to add scale(). */
  transform: translateY(-50%);
  transform-origin: top left;
  /* Make the title occupy a box with a known center.
     Matching the square button size guarantees center-Y alignment. */
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  display: flex;
  align-items: center;
  justify-content: center;
}

.title a {
  display: block;
  text-align: left;
  font-size: var(--title-font-size);
  font-weight: 600;
  line-height: 1;
  letter-spacing: .05em;
  color: var(--header-text);
  text-decoration: none;
  /* No outline/stroke on the title text */
  text-shadow: none;
  -webkit-text-stroke: 0;
  filter: none;
  transition: color var(--theme-transition) ease;
}

/* Prevent the browser's default visited-link purple from leaking into the title. */
.title a:link,
.title a:visited,
.title a:hover,
.title a:active,
.title a:focus,
.title a:focus-visible {
  color: var(--header-text);
}

/* ================== Mode Toggle (Triangle) ================== */
.mode-toggle {
  cursor: pointer;
  background: transparent;
}

/* Text-based mode toggle variant: hide the decorative parts and show text */
/* Triangle mode toggle: draw an isosceles triangle with borders and rotate on .active */
.mode-toggle.mode-toggle-text {
  /* Make the toggle element a square the same size as the wrapper/circle so
     the triangle pseudo-element can use percentage positioning to center
     correctly. This ensures the geometric center of the triangle aligns
     with the scroll-circle center. */
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  padding: 0;
  display: inline-block;
  position: relative;
  cursor: pointer;
  background: transparent;
  border-color: transparent;
  /* hide any accidental text nodes */
  text-indent: -9999px;
  overflow: visible;
  z-index: 10000;
}

/* The wrapper uses flex centering; keep the toggle in normal flow so there are
   no competing positioning systems (fixed wrapper + absolute child). */
.toggle-wrapper .mode-toggle.mode-toggle-text {
  position: relative;
  left: auto;
  top: auto;
  transform: none;
}

.mode-toggle.mode-toggle-text::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  width: 0;
  height: 0;
  /* triangle size controlled via variables */
  border-left: var(--toggle-triangle-half) solid transparent; /* half the base */
  border-right: var(--toggle-triangle-half) solid transparent; /* half the base */
  border-bottom: var(--toggle-triangle-height) solid var(--header-text);
  transform-origin: center;
  /* Align the triangle's *centroid* to the control center.
     For an equilateral-ish triangle, the centroid is offset by h/6 from the
     bounding-box center when the triangle is drawn with border-bottom.
     This keeps the triangle visually centered on the same Y as the menu square. */
  transform: translate(-50%, calc(-50% + (var(--toggle-triangle-height) / 6))) scaleY(1);
  transition: transform var(--theme-transition) ease, border-bottom-color var(--theme-transition) ease;
}

/* Mirror vertically about the center when active */
.mode-toggle.active.mode-toggle-text::after,
.mode-toggle.mode-toggle-text.active::after {
  transform: translate(-50%, calc(-50% + (var(--toggle-triangle-height) / 6))) scaleY(-1);
}

.mode-toggle.mode-toggle-text::before {
  display: none; /* hide decorative toggle pieces */
}

/* No textual color rules needed; triangle color follows --header-text and transitions via border-bottom-color */

/* ================== Hamburger ================== */
.menu-btn {
  position: absolute;
  top: var(--ui-top);
  /* horizontally align with other UI elements using the single anchor --ui-right */
  right: var(--ui-right);
  transform: translateY(-50%);
  /* square size that matches the scroll-circle for visual alignment */
  width: var(--scroll-circle-size);
  height: var(--scroll-circle-size);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0; /* no inner padding for a solid square */
  cursor: pointer;
  /* above the menu overlay */
  z-index: 100001;
  background: var(--header-text); /* solid square uses header text color (black/white) */
  /* remove border/outline so it's a clean filled square; shadow retained if needed */
  outline: none;
  border: none;
  box-shadow: none;
  box-sizing: border-box;
  transition: transform var(--menu-transition-speed) ease, background var(--theme-transition) ease;
}

/* rotate the filled square when active/open */
.menu-btn.active {
  transform: translateY(-50%) rotate(45deg);
}

.menu-btn span { display: none; }


/* ================== Menu ================== */

/* Full-viewport overlay menu. When closed it's off-screen (right:-100%),
   when open it covers the viewport and shows its own scrollbar on the LEFT.
   We intentionally override the global scrollbar hiding for this element. */
.menu {
  position: fixed;
  top: 0;
  bottom: 0;
  /* Keep the menu in-place and fade it in/out (no sliding) */
  left: calc((100% - var(--menu-overlay-width)) / 2);
  right: calc((100% - var(--menu-overlay-width)) / 2);
  width: var(--menu-overlay-width);
  height: 100vh;
  background: white;
  /* Match the page theme transition so the menu doesn't flash between themes */
  transition: opacity var(--menu-transition-speed) ease, background var(--transition-speed) ease;
  z-index: 99999;
  overflow-y: auto;
  /* Space at the top so menu content doesn't sit under header controls.
     Controlled by --menu-top-padding so it can be tuned per breakpoint. */
  padding-top: var(--menu-top-padding);
  padding-left: 0;
  padding-right: 0;
  padding-bottom: 0;
  /* Hide the native scrollbar for the menu overlay (we use a custom circular
    scrollbar). Keep smooth touch scrolling enabled. */
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; /* Firefox: hide */
  scrollbar-color: transparent transparent; /* fallback */

  /* Closed state */
  opacity: 0;
  pointer-events: none;
}

/* Keep the two-column grid layout stable so the menu doesn't "jump" vertically
   when toggling open/closed. */
.menu .menu-grid {
  height: calc(100vh - var(--menu-top-padding));
}

/* When we're using the JS-built two-column grid, make the overlay itself
  non-scrollable so the right column is the only scroll container.
  (Use a class instead of :has() for mobile compatibility.) */
.menu.open.menu-grid-mode {
  overflow: hidden;
}

/* Even when closed (opacity 0), prevent the overlay from becoming a second
  scroll container in grid mode. */
.menu.menu-grid-mode {
  overflow: hidden;
}

body.dark-mode .menu,
html.dark-mode body .menu { background: black; }

/* When the menu is open we show it (fade in) */
.menu.open {
  opacity: 1;
  pointer-events: auto;
}

/* Two-column menu grid used by the JS initializer. Left column is the
   static category selector (does not scroll). Right column is the
   scrollable content area (this is the menuScrollTarget). */
.menu-grid {
  display: grid;
  /* Shift the column separation left (~15%): left column narrower, right column wider */
  grid-template-columns: 35% 65%;
  gap: 2.5rem;
  align-items: start;
  padding: var(--page-pad);
  /* Height is controlled by .menu.open .menu-grid so it's consistent with the
     menu's top padding when open. */
  height: auto;
  width: 100%;
  min-width: 0;
}

/* Mid-size screens: slightly smaller left column and larger right column. */
.menu-left {
  padding-right: 1rem;
  display: flex;
  flex-direction: column;
  gap: 4rem; /* more spacing between categories */
  align-items: flex-end; /* categories align to the right edge */
  /* left column intentionally does NOT scroll */
  overflow: visible;
  min-width: 0;
}
.menu-category-btn {
  font-size: 2.6rem; /* large legible category labels */
  background: transparent;
  border: none;
  padding: 0;
  cursor: pointer;
  font-weight: 700;
  color: var(--header-text);
  text-align: right;
  display: inline-block; /* so transform doesn't affect surrounding layout */
  transform-origin: right center;
  transition: transform 160ms ease;
}
.menu-category-btn:hover,
.menu-category-btn:focus-visible,
.menu-category-btn.active {
  transform: scale(1.2);
}
.menu-category-btn.active { text-decoration: underline; }
.menu-right {
  padding-left: 1rem;
  /* make the right column itself a flex column that contains the scrollable content */
  display: flex;
  flex-direction: column;
  align-items: flex-start; /* keep subcategory content left-aligned */
  overflow: visible; /* allow scaled children to render outside without clipping */
  min-height: 0; /* critical for nested scroll containers in Chrome */
  height: 100%;
  min-width: 0;
}
.menu-right-content {
  overflow-y: auto; /* this is the scroll target used by JS */
  padding-right: 1rem;
  padding-left: 0.8rem; /* breathing room so scaled buttons don't clip on the left edge */
  /* Note: the visible "end padding" needs to be on the final child inside the
     scroll container (UL / menu-content), not just on the scroller itself,
     because some nested elements can collapse spacing at the bottom. */
  padding-bottom: 0;
  /* Let this flex item actually shrink and scroll in Chrome */
  min-height: 0;
  height: 100%;
  width: 100%;
  min-width: 0;
}

/* Add breathing room below whatever content is currently mounted in the
   right column (About/Contact/Projects). */
.menu-right-content > :last-child {
  padding-bottom: 9rem;
}

/* Extra "footer" spacer so the end of the list never feels cramped,
   even if the last child doesn't accept padding the way we expect. */
.menu-right-content::after {
  content: '';
  display: block;
  height: 9rem;
}

/* Mobile accordion menu (JS swaps to this on small screens) */
.menu-accordion {
  width: 100%;
  padding: 2.5rem 1.25rem;
}
.menu-accordion-section {
  width: 100%;
  margin-bottom: 1.25rem;
}
.menu-accordion-section > .menu-category-btn {
  width: 100%;
  text-align: left;
}
.menu-accordion-panel {
  margin-top: 0.75rem;
  padding-left: 0.75rem; /* slight indent under heading */
}



/* Keep inner content LTR so text/layout doesn't flip */
.menu * { direction: ltr; }

/* Restore WebKit scrollbars for the overlay (overrides the global hide) */
.menu::-webkit-scrollbar { width: 0; height: 0; }
.menu::-webkit-scrollbar-track { background: transparent; }
.menu::-webkit-scrollbar-thumb { background: transparent; }

.menu ul {
  list-style: none; /* remove bullets */
  padding: 0;

}

.menu ul .submenu {
  display: none; /* hide all submenus by default */
  padding-left: 2rem; /* indent submenu */
  margin-top: 0rem;  /* spacing between submenu items */
}

/* The two-column menu renders a "right column submenu" that must always be visible.
   Keep it unindented so it aligns nicely with the right column content edge. */
.menu .menu-right-content .submenu-right {
  display: block;
  padding-left: 0;
}

.menu-category {
  cursor: pointer; 
  font-size: 1.6rem;  /* larger category text */
  font-weight: 600;
  padding-left: 2rem;
  margin-bottom: 1rem; /* spacing between categories */
  padding-top: 2rem;

  /* scale interaction */
  display: inline-block;
  transform-origin: left center;
  transition: transform 160ms ease;

}

.menu-category:hover {
  text-decoration: underline;
}

.menu-category:hover,
.menu-category:focus-visible,
.menu-category:active {
  transform: scale(1.2);
}

.menu ul li a {
  display: block;
  font-size: 1.4rem;   /* larger link text */
  margin: 0.5rem 0;    /* spacing between links */
  text-decoration: none;
  /* scale interaction */
  transform-origin: left center;
  transition: transform 160ms ease;
}

.menu ul li a:hover,
.menu ul li a:focus-visible,
.menu ul li a:active {
  transform: scale(1.2);
}

/* Menu content buttons (right column). These should behave like the
   left-column `.menu-category-btn`, but with left-aligned text and a
   smaller font size.

   IMPORTANT: Keep this independent from legacy `.btn-1`, because many
   non-menu pages still use `.btn-1` and should not inherit menu-only
   interactions. */
.menu-content-btn {
  background: transparent;
  border: none;
  padding: 0.35rem 0;
  cursor: pointer;
  font-family: 'Noto Sans', sans-serif;
  font-weight: 700;
  color: var(--header-text);
  text-align: left;
  display: inline-block;
  transform-origin: left center;
  transition: transform 160ms ease;
  font-size: 1.8rem;
}

.menu-content-btn:hover,
.menu-content-btn:focus-visible,
.menu-content-btn:active {
  transform: scale(1.2);
}

/* Contact submenu: match the entry typography (size/weight) used in About.
   Keep this scoped so Projects/About lists can stay independently tuned. */
.menu #contact .menu-content-btn {
  font-size: 1.55rem;
  font-weight: 800;
}

/* About submenu section headers (EXPERIENCE / EDUCATION) */
.menu-content-btn.about-heading {
  font-size: 1.55rem;
  font-weight: 800;
  letter-spacing: 0.02em;
}

/* Ensure menu items inherit the theme color. (Don't touch .btn-1 here.) */
.menu-category,
.menu ul li a,
.menu-content-btn {
  color: black;
  transition: color 0s ease;
}

body.dark-mode .menu-category,
body.dark-mode .menu ul li a,
body.dark-mode .menu-content-btn,
html.dark-mode body .menu-category,
html.dark-mode body .menu ul li a,
html.dark-mode body .menu-content-btn {
  color: white;
}

.scroll-page {
  width: 100%;
  max-width: 1080px;
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow-x: hidden;
  margin-left: auto;
  margin-right: auto;
  padding: var(--page-pad);
  padding-bottom: 200px;
  box-sizing: border-box;
}

.scroll-content {
  width: 100%;
  max-width: 1080px;
  padding: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  box-sizing: border-box;
}

/* ================== Lists ================== */
.scroll-page ul {
  list-style: none;
  padding: 0;
  margin: 0;
  width: 100%;
  box-sizing: border-box;
}

.scroll-page ul li {
  margin-bottom: 2rem;
  width: 100%;
  box-sizing: border-box;
}

.scroll-page ul li img,
.scroll-page ul li video {
  width: 100%;
  height: auto;
  max-width: 100%;
  display: block;
  box-sizing: border-box;
}

.scroll-page ul br { display: none; }

/* ================== Fonts & Buttons ================== */
h1,h2,h3,h4,h5,p { font-family: var(--rootfont); font-weight: 100; margin: 0; }
h1{ font-size:1.3em; line-height:1.5em; }
h2{ font-size:1.4em; line-height:2em; font-weight:600; }
h3{ font-size:1.2em; line-height:1.2em; font-style:italic; }
h4{ font-size:1.2em; line-height:1.5em; margin:20px 0; font-weight:100; }
h5{ font-size:1.5em; line-height:1.5em; margin:20px 0 10px 0; font-weight:600; text-transform:uppercase; }
p{ font-size:1.8em; line-height:1.4em; margin:10px 0 20px 0; }

.btn-12 {
  border: none;
  background: transparent;
  outline: none;
  font-family: var(--rootfont);
  transition: all .5s ease;
  text-align: left;
  color: var(--primary-color);
}

/* ================== Project Media ================== */
.project .light-mode-img,
.project .light-mode-video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 1;
  /* Crossfade opacity using the theme transition (fast UI change) while keeping transform on the long transition */
  transition: opacity var(--theme-transition) ease, transform var(--transition-speed) ease;
  z-index: 1;
  /* round the visible image to match the project container */
  border-radius: inherit;
  will-change: opacity, transform;
}

.project .dark-mode-img,
.project .dark-mode-video {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  opacity: 0;
  /* Crossfade opacity using the theme transition so it fades in/out with light image */
  transition: opacity var(--theme-transition) ease, transform var(--transition-speed) ease;
  z-index: 0;
  /* round the dark-mode image to match the project container */
  border-radius: inherit;
  will-change: opacity, transform;
}

body.dark-mode .project .light-mode-img,
body.dark-mode .project .light-mode-video,
html.dark-mode body .project .light-mode-img,
html.dark-mode body .project .light-mode-video { opacity: 0; }

body.dark-mode .project .dark-mode-img,
body.dark-mode .project .dark-mode-video,
html.dark-mode body .project .dark-mode-img,
html.dark-mode body .project .dark-mode-video { opacity: 1; }


/* ================== Responsive Section ================== */

/* General containers */
.menu-content {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: flex-start;
  width: 100%;
  box-sizing: border-box;
}

/* Main Grid */
main {
  padding: 2rem;
  display: grid;
  gap: 2rem;
  width: 100%;
  max-width: 1200px;
  margin: 0px auto 0;
  grid-template-columns: 1fr; /* default 1 column */
  box-sizing: border-box;
}

/* Project items */
.project {
  position: relative;
  cursor: pointer;
  border-radius: 24px;
  /* allow the overlay to sit outside the image box */
  overflow: visible;
  width: 100%;
  aspect-ratio: 1/1;
  display: flex;
  justify-content: center;
  align-items: center;
  background: white;
  transition: background var(--transition-speed) ease;
}

.project img,
.project video {
  width: 100%;
  height: 100%;
  object-fit: cover; /* responsive fit */
  display: block;
  /* ensure any plain img/video children also have rounded corners */
  border-radius: inherit;
}

/* Project overlay: position it outside/below the image box without changing grid flow */
.project .overlay {
  position: absolute;
  top: 100%;               /* place immediately below the image container */
  left: 0;
  transform: none;
  padding: 1rem 0  .2rem 0; /* keep vertical padding, remove horizontal centering */
  width: 100%;
  background: transparent;
  font-weight: 100;
  font-family: var(--rootfont);
  font-size: 1.3rem;
  text-align: left; /* align text to left edge of project image */
  z-index: 2;
  opacity: 1;              /* always visible below the image */
  border-radius: 0px;
  display: block;
  transition: opacity var(--transition-speed) ease, transform var(--transition-speed) ease;
  white-space: normal;
  -webkit-text-fill-color: black !important;
}

/* Dark mode: white text */
body.dark-mode .project .overlay,
html.dark-mode body .project .overlay {
  -webkit-text-fill-color: white !important;
}

/* ================== Media Queries ================== */

/* NOTE: This section is intentionally located at the END of the stylesheet so
   responsive overrides are easy to find and don't get accidentally overridden
   by later base rules. */

/* Small devices: 0 - 599px */
@media (max-width: 599px) {
  :root {
    --ui-offset: 7px;
    --ui-scale: 0.4;
    --menu-scroll-gap: 10px;
    --toggle-line-width: 4px;
    --toggle-line-height: 48px;
    --toggle-circle-size: 34px;
    --hamburger-line-height: 3px;
    --hamburger-line-spacing: 2px;
    /* Title: move down slightly so the initial scaled state doesn't clip */
    --title-top: 18px;
    /* Reduce outline so the stacked title lines don't overlap when scaled */
    --stroke-thickness: 1.5px;

    /* Menu: reduce the reserved top space on small screens */
    --menu-top-padding: 80px;

    --page-pad: 23px;
  }

  /* Reduce the fixed header's footprint on small screens */
  header {
    height: 70px;
  }
  body {
    padding-top: 70px;
  }

  /* Menu layout tweaks for small screens (paired with JS menu accordion/grid behavior). */
  main {
    grid-template-columns: 1fr;
    padding: var(--page-pad);
    margin-top: 0px;
  }

  /* Small screens: stack the two-column menu into one column. */
  .menu .menu-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
    padding: 1.75rem 1.25rem;
    height: auto;
  }

  .menu .menu-left {
    align-items: flex-start;
    padding-right: 0;
    gap: 1.25rem;
  }

  .menu .menu-category-btn {
    text-align: left;
    transform-origin: left center;
    font-size: 1.6rem;
  }

  .menu .menu-right {
    padding-left: 0;
  }

  /* Keep the right column as the scroll container on small screens.
     This matches the JS wheel/scroll-circle logic which targets `.menu-right-content`. */
  .menu .menu-right-content {
    overflow-y: auto;
    height: calc(100vh - var(--menu-top-padding) - 1.75rem);
    padding-left: 0;
    padding-right: 0;
    -webkit-overflow-scrolling: touch;
  }

  /* On small screens, align the menu scrollbar indicator to the right-content box. */
  body.menu-open .menu {
    position: fixed;
  }

  body.menu-open .menu-scroll-circle,
  body.menu-open .menu-scroll-track {
    position: fixed;
    z-index: 100001;
  }

  /* Align circle centers: same centerline as the main scroll circle. */
  body.menu-open .menu-scroll-circle {
    right: calc(var(--ui-right) + (var(--scroll-circle-size) - var(--menu-scroll-size)) / 2);
  }
  .project { aspect-ratio: 1/1; }

  /* Project overlay: smaller text on small devices */
  .project .overlay {
    font-size: 0.9rem;
  }

  /* Menu overlay: smaller, denser typography on very small screens.
     Scoped to the overlay so site-wide `.btn-1` styles stay unchanged. */
  .menu .menu-category {
    font-size: 0.5rem;
    padding-left: 1.25rem;
    padding-top: 1.2rem;
    margin-bottom: 0.75rem;
  }
  .menu .menu-right-content .menu-category { padding-left: 0.75rem; }

  .menu .menu-content-btn {
    font-size: 1rem;
    line-height: 1.5rem;
    padding-left: 30px;
    margin-bottom: 0.35rem;
  }

  /* If the right column is rendering a flat list, remove indent and keep it tight */
  .menu .menu-right-content ul {
    padding-left: 0;
  }
  .menu .menu-right-content li { margin: 0; }
}

/* Medium devices: 600px - 1079px */
@media (min-width: 600px) and (max-width: 1079px) {
  :root {
    --ui-offset: 20px;
    --ui-scale: .75;
    --menu-scroll-gap: 12px;
    --toggle-line-width: 5px;
    --toggle-line-height: 56px;
    --toggle-circle-size: 40px;
    --hamburger-line-height: 3px;
    --hamburger-line-spacing: 2px;

    --page-pad: 100px;
  }

  /* Main page: add more breathing room on medium screens */
  main {
    padding: var(--page-pad);
    margin-top: 0px;
  }

  /* Menu grid: slightly smaller left column and larger right column. */
  .menu .menu-grid {
    grid-template-columns: 30% 70%;
    gap: 2rem;
    padding: var(--page-pad);
  }

  .menu-content, .scroll-content { max-width: 700px; }
  main { grid-template-columns: 1fr; }

  /* Menu typography tweaks for this breakpoint */
  .menu-content-btn { font-size: 1.5rem; }
  .menu-category-btn { font-size: 2rem; }
  .menu .menu-right { padding-left: 0; }

  /* Align menu scroll circle center-to-center with the main scroll circle */
  body.menu-open .menu-scroll-circle {
    right: calc(var(--ui-right) + (var(--scroll-circle-size) - var(--menu-scroll-size)) / 2);
  }
}

/* Large-screen menu layout used across all wide viewports */
@media (min-width: 1080px) {
  .menu.open > ul {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2.5rem;
    align-items: start;
    padding: 2.5rem 4rem;
  }

  .menu.open > ul > li { width: 100%; }
  .menu.open .submenu { max-height: none; overflow: visible; }

  .menu.open > ul > li:first-child {
    padding-right: 1rem;
    border-right: none;
  }

  .menu.open > ul > li:nth-child(2) {
    padding-left: 1rem;
  }

  .menu.open > ul > li > .menu-category {
    position: static;
    top: auto;
    z-index: auto;
  }
}

/* Large devices: 1080px - 1599px */
@media (min-width: 1080px) and (max-width: 1599px) {
    :root {
    --ui-offset: 40px;
    --ui-scale: 1;
    --menu-scroll-gap: 12px;
    --toggle-line-width: 5px;
    --toggle-line-height: 56px;
    --toggle-circle-size: 40px;

    --page-pad: 60px;
  }
  .menu-content, .scroll-content { max-width: 800px; }
  main { grid-template-columns: repeat(2, 1fr);
    padding: var(--page-pad);
        margin-top: 0px;

 }
 
  /* Align menu scroll circle center-to-center with the main scroll circle */
  body.menu-open .menu-scroll-circle {
    right: calc(var(--ui-right) + (var(--scroll-circle-size) - var(--menu-scroll-size)) / 2);
  }
  .menu-grid {
    padding: 10px var(--page-pad) 10px var(--page-pad);
  }

  }


/* Extra large devices: 1600px+ */
@media (min-width: 1600px) {
      :root {
    --ui-offset: 50px;
    --ui-scale: 1.2;
    --menu-scroll-gap: 15px;
    --toggle-line-width: 5px;
    --toggle-line-height: 56px;
    --toggle-circle-size: 40px;
    --page-pad: 80px;
  }
  .menu-content, .scroll-content { max-width: 1080px; }
  main { grid-template-columns: repeat(2, 1fr); }

  /* Align menu scroll circle center-to-center with the main scroll circle */
  body.menu-open .menu-scroll-circle {
    right: calc(var(--ui-right) + (var(--scroll-circle-size) - var(--menu-scroll-size)) / 2);
  }
    .menu-grid {
    padding: 10px var(--page-pad) 10px var(--page-pad);}
}
