:root {
  --background: #fcfcfc;
  --foreground: #000000;
  --heading-color: #000000;
  --heading-size: 12px;
  --primary: #000000;
  --secondary: #0a0a0a;
  --muted: #222222;
  /* Accent link decoration — site-wide, controlled in GENERAL. Accent links
     read these so "Accent underline" / "Accent underline on hover" flip the
     whole site at once. */
  --accent-deco: none;
  --accent-deco-hover: none;
  --font-body: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-heading: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --font-body-weight: normal;
  --font-heading-weight: normal;
  --text-transform: none;
}

/* ===== Reset ===== */
section, div, article, figcaption, figure, applet, object, iframe, blockquote, pre, hr, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strong, sub, sup, tt, var, b, u, i, dl, dt, dd, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, aside, canvas, details, hgroup, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  vertical-align: baseline;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  margin: 0;
  padding: 0;
  width: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow-x: hidden;
  font-family: var(--font-body);
  font-weight: var(--font-body-weight, normal);
  text-transform: var(--text-transform, none);
  color: var(--foreground);
  background-color: var(--background);
  /* Mobile base: bumped from the editorial 12px so phone reading isn't
     hostile. Desktop restores 12px below. */
  font-size: 12px;
}

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

h1, h2, h3, h4, h5, h6, span {
  margin: 0;
  padding: 0;
}

a {
  text-decoration: none;
  /* Reads the cascading --link-color custom property (set by any ancestor
     element via a text_color style override; see render/style.ts), with the
     theme foreground as fallback. This is what lets
     header_nav_style.text_color actually recolor the nav links — the
     element-selector for a wins over inherited color, but using a
     custom-property var lets the override flow through. */
  color: var(--link-color, var(--foreground));
  /* Links: a HEADER/FOOTER section override (--link-transform) wins; otherwise
     fall back to the site-wide GENERAL transform (--text-transform) so the
     General setting reaches links too; otherwise none. */
  text-transform: var(--link-transform, var(--text-transform, none));
  /* Size + weight come from CSS vars set per nav/footer block (link_size /
     link_weight → --link-font-size / --link-font-weight in render/style.ts),
     with sensible defaults. Using vars (not a fixed value) is what lets the
     panel's Link size/weight actually affect the links. */
  font-size: var(--link-font-size, 12px);
  font-weight: var(--link-font-weight, bold);
}

a:hover {
  /* Per-element hover_color override (4f.8) takes precedence; theme.primary
     is the fallback. Inline style on a parent element can set --hover-color
     to recolor hover within that subtree without touching the theme. */
  color: var(--hover-color, var(--primary));
  transition: 0.3s ease-in-out;
  -webkit-transition: 0.3s ease-in-out;
  -moz-transition: 0.3s ease-in-out;
}

p { margin: 0; line-height: 1.2; }

iframe, img, embed, object, video { max-width: 100%; }
img { width: 100%; height: auto; max-width: 100%; }

textarea, input[type="text"], input[type="button"], input[type="submit"] {
  appearance: none;
  border-radius: 0;
}
input:focus { outline: none; }
input { background: transparent; }

/* ===== Wrapper ===== */
.wrapper {
  width: 100%;
  padding-left: 12px;
  padding-right: 12px;
  padding-bottom: 12px;
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  min-height: 100vh;
  transition: all 0.25s ease;
}
.site-header { grid-row: 1; }
.header-hero { grid-row: 2; }
.main { grid-row: 3; }
.site-footer { grid-row: 4; }

/* ===== Clearfix ===== */
.clearfix:after {
  content: '';
  display: block;
  clear: both;
  visibility: hidden;
  line-height: 0;
  height: 0;
}

/* ===== Page loader + fade-in (pure CSS) =====
   A centered pulsing dot covers the page on load, then fades out as the
   content fades in. Shown on every page load (refresh + navigating to a
   project page). Size comes from --loader-size (default 60px), color from
   --loader-color (default white) — both set inline per-page from the
   loader config. Emitted only when loader.visible is true (the .has-loader
   class on .wrapper gates the content fade-in to match). */
.page-loader {
  position: fixed;
  inset: 0;
  z-index: 9999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--background);
  /* Hold briefly, then fade out. A small inline script sets display:none on
     animationend so a Chrome-mobile repaint (address-bar collapse) can't flash
     the loader's pre-fill state back in afterwards. */
  animation: rabbitLoaderOut 0.7s ease 0.6s forwards;
}
.page-loader.is-done { display: none !important; }
.page-loader .loader-dot {
  width: var(--loader-size, 60px);
  height: var(--loader-size, 60px);
  border-radius: 50%;
  background: var(--loader-color, #ffffff);
  animation: rabbitLoaderPulse 1.1s ease-in-out infinite;
}
@keyframes rabbitLoaderPulse {
  0%, 100% { transform: scale(1);    opacity: 1; }
  50%      { transform: scale(0.55); opacity: 0.45; }
}
@keyframes rabbitLoaderOut {
  to { opacity: 0; visibility: hidden; }
}
.wrapper.has-loader {
  animation: rabbitFadeIn 0.7s ease 0.45s both;
}
@keyframes rabbitFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ===== Header ===== */
.site-header {
  width: 100%;
  /* min-height keeps tap targets reasonable on mobile; desktop overrides
     back to the exact 35px below. */
  min-height: 44px;
  background: transparent;
  position: relative;
}

nav.header-nav {
  width: 100%;
  position: relative;
  top: 8px;
}

ul.header-menu-index {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  /* Wrap on narrow phones so nav doesn't overflow / overlap. Desktop
     never wraps because there's plenty of room. */
  flex-wrap: wrap;
  gap: 8px;
}

/* Nav links use the GENERAL Accent color by default (per-block "Link color"
   still wins via --link-color); hover = Secondary (Accent hover); underline
   from the GENERAL toggles. */
nav.header-nav a {
  color: var(--link-color, var(--primary));
  text-decoration: var(--accent-deco, none);
}
nav.header-nav a:hover {
  color: var(--hover-color, var(--secondary));
  text-decoration: var(--accent-deco-hover, none);
}

/* Hero margins scale fluidly between phone (40px) and desktop (150px)
   without needing breakpoint jumps. 12vw is the elastic midpoint. */
.header-hero {
  margin-bottom: clamp(40px, 12vw, 150px);
}

.header-hero-image {
  width: 100%;
  height: auto;
  position: relative;
  top: -5px;
}

/* ===== Main ===== */
.main {
  width: 100%;
  height: 100%;
}

.main h1.page-title {
  font-size: var(--heading-size, 20px);
  font-weight: var(--font-heading-weight, normal);
  font-family: var(--font-heading);
  color: var(--heading-color, var(--foreground));
  display: none; /* hidden by template design — set display: block to show */
}

/* ===== Container ===== */
.container {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

/* ===== Grid (image galleries: Home, Work, Board) =====
   Mobile-first: always 1 column on phones for legible image sizes.
   Tablet+ honors per-page layout dials emitted as inline CSS custom
   properties on the .grid wrapper:
     --grid-cols   default 2, accepts 2/3/4 (from pages.<key>.layout.columns)
     --grid-gap    default 14px, mapped from sm/md/lg in pages.ts
     --img-aspect  default auto, mapped from square/wide/portrait
*/
/* Masonry via CSS multi-column (no JS / no CDN — clean for static bundles).
   Cards flow top-to-bottom into N columns, each kept whole (break-inside).
   Mobile = 1 column. Natural image heights (the default 'original' aspect)
   produce the staggered masonry look; a fixed image_aspect makes the columns
   uniform instead. Column count comes from --grid-cols, gaps from --grid-gap
   (column-gap for horizontal, item margin-bottom for vertical). */
.grid {
  column-count: 1;
  column-gap: var(--grid-gap, 12px);
}

.grid > div {
  cursor: zoom-out;
  width: 100%;
  margin-bottom: var(--grid-gap, 12px);
  break-inside: avoid;
}

/* Apply aspect-ratio to every grid image so cells stay uniform when the
   user picks a fixed aspect. 'auto' (default) lets natural aspect win. */
/* Descendant (not just direct child) so it also covers images wrapped in an
   .item-link. display:block kills the inline-image baseline gap that otherwise
   shows at the bottom of a card when project titles are hidden. */
.grid > div img {
  display: block;
  aspect-ratio: var(--img-aspect, auto);
  object-fit: cover;
  width: 100%;
  /* Gentle fade-in as lazy images load (the masonry script sets opacity 0 on
     not-yet-loaded images, then 1 on load). No base opacity here, so images
     stay visible if JS doesn't run. */
  transition: opacity 0.45s ease;
}

/* Progressive reveal: the masonry script hides items beyond the first batch;
   scrolling reveals them in chunks via IntersectionObserver. The class is
   added by JS only, so no-JS keeps all items visible (CSS multi-column
   fallback). !important wins over any inline width/margin Masonry sets. */
.grid-deferred { display: none !important; }

/* ===== Project-card titles (captions under grid images) =====
   Page-level styling arrives as CSS custom properties on the .grid wrapper
   (see pages.ts):
     --title-align            left | center | right   (default left)
     --title-color            caption color           (default --foreground)
     --title-hover-color      hover color             (default --primary)
     --title-decoration       underline | (unset)     base underline
     --title-decoration-hover underline | (unset)     hover underline
   Titles are only emitted when the page's project_titles.visible is true AND
   the card has title text, so the default (title-less) grid is unchanged. */
.grid .item-link {
  display: block;
  cursor: pointer;
  color: inherit;
}
.grid .project-title {
  display: block;
  margin-top: 8px;
  /* Follow the GENERAL site-wide transform + body weight (no per-title
     transform/weight control), so the General panel reaches project titles. */
  text-transform: var(--text-transform, none);
  font-weight: var(--font-body-weight, normal);
  font-size: var(--title-font-size, 12px);
  padding-left: var(--title-padding-left, 0);
  text-align: var(--title-align, left);
  color: var(--title-color, var(--primary));
  text-decoration: var(--title-decoration, var(--accent-deco, none));
  transition: color 0.3s ease-in-out;
}
.grid .item-link:hover .project-title,
.grid .project-title:hover {
  color: var(--title-hover-color, var(--secondary));
  text-decoration: var(--title-decoration-hover, var(--accent-deco-hover, none));
}

/* ===== Site Description (above the grid on Home / Work / Board) =====
   Mobile-first: the inner paragraph is full width with no offset. Tablet
   narrows it to 50% and centers it (left:50%). Desktop narrows further to 25%
   and honors the per-page alignment preset emitted as --desc-left
   (a=0% / b=25% / c=50%) on .description-paragraph. The container is always
   100% wide. */
.site-description {
  width: 100%;
  margin-bottom: -30px;
}
/* Small phones (≤500px): smaller pull-up so the paragraph doesn't crowd. */
@media (max-width: 500px) {
  .site-description {
    margin-bottom: -10px;
  }
}
.site-description .description-paragraph {
  width: 100%;
  position: relative;
  left: 0;
  margin-bottom: clamp(24px, 6vw, 60px);
}
/* font-size + line-height come from the panel (inline on the <p>); the base
   <p> line-height (1.2) is the default. */

/* ===== Studio Page =====
   Rewritten in 4f.8-prereq from float-based 50/25/25 to CSS Grid so it
   stacks cleanly on mobile.

   Original HTML structure preserved:
     .page-content
       .content-image       (the studio photo)
       .content             (wrapper)
         h1.content-title
         p.content-paragraph

   Layout per breakpoint:
     mobile  — single stack (image, title, paragraph all full width)
     tablet  — 2-col: image | (title + paragraph stacked)
     desktop — 3-col feel via nested grid: image | (title | paragraph)
               which restores the original editorial 50/25/25 look.
*/
.page-content {
  width: 100%;
  clear: both;
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
}

.page-content .content {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0px;
  width: 98%;
}

/* Mode block (.page-content.mode-block): no gap between the image/content halves. */
.page-content.mode-block {
  gap: 0px;
}

.page-content .content-image {
  width: 98%;
}
/* Mobile (≤768px): the studio/content image goes full-width. */
@media (max-width: 768px) {
  .page-content .content-image { width: 100%; }
}

.page-content .content-title {
  font-size: var(--bio-heading-size, var(--heading-size, 12px));
  /* Headings follow the GENERAL Heading weight control (separate from Body
     weight) — set Heading weight to Bold for bold headings. */
  font-weight: var(--font-heading-weight, normal);
  font-family: var(--font-heading);
  color: var(--bio-heading-color, var(--heading-color, inherit));
}

.page-content .content-paragraph {
  font-size: var(--bio-body-size, inherit);
  line-height: var(--bio-body-line, 1.3);
}

/* ===== Row-based content (Bio rows + Mode block) =====
   Lives inside .page-content .content (the Details half). Each .content-row is
   a grid of .content-col cells. data-cols drives the column count: Bio = 2
   equal 50% columns, Mode = 3 equal 33.3% columns from tablet upward. Mobile
   stays a single column. All typography reads the same --bio-* vars the panel
   sliders/colors drive. */
.content-rows { display: flex; flex-direction: column; gap: 24px; width: 100%; grid-column: 1 / -1; }
.content-row { display: grid; grid-template-columns: 1fr; gap: 10px 24px; }
/* Below 768px: Mode (3-col rows) keeps 2 columns; Bio (2-col rows) stays the
   base 1 column. At 768px+ the media query below restores 3 / 2 respectively. */
.content-row[data-cols="3"] { grid-template-columns: repeat(2, 1fr); }
.content-col { min-width: 0; }
.content-col-heading {
  margin: 0 0 6px;
  font-family: var(--font-heading);
  /* Headings follow the GENERAL Heading weight control (separate from Body
     weight) — set Heading weight to Bold for bold headings. */
  font-weight: var(--font-heading-weight, normal);
  text-transform: var(--text-transform, none);
  font-size: var(--bio-heading-size, var(--heading-size, 12px));
  color: var(--bio-heading-color, var(--heading-color, inherit));
}
.content-col .rows-text,
.content-col .rows-paragraph {
  margin: 0;
  font-size: var(--bio-body-size, inherit);
  line-height: var(--bio-body-line, 1.3);
}
.content-col .rows-list,
.content-col .rows-links { list-style: none; margin: 0; padding: 0; }
.content-col .rows-list li,
.content-col .rows-links li {
  font-size: var(--bio-body-size, inherit);
  line-height: var(--bio-body-line, 1.3);
}
.content-col .rows-link,
.content-col .rows-links a {
  color: var(--link-color, var(--primary));
  text-decoration: var(--accent-deco, none);
  font-size: var(--bio-body-size, inherit);
}
.content-col .rows-link:hover,
.content-col .rows-links a:hover { color: var(--hover-color, var(--secondary)); text-decoration: var(--accent-deco-hover, none); }
@media (min-width: 769px) {
  .content-row[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
  .content-row[data-cols="3"] { grid-template-columns: repeat(3, 1fr); }
}
/* ≤768px (Mode only): the 3-col rows show 2 columns. Hide empty cells so gaps
   vanish, and on rows where every cell is filled drop the heading cell so the
   two content columns sit side by side (see renderContentRows data-collapse-head).
   Bio (data-cols=2) is untouched here and stays 1 column. */
@media (max-width: 768px) {
  .mode-block .content-col:empty { display: none; }
  .mode-block .content-row[data-collapse-head="1"] > .content-col:first-child { display: none; }
}
/* Image content (Paragraph block; available to any rows-* content). */
.content-col .rows-image,
.paragraph-content .rows-image { display: block; width: 100%; height: auto; }

/* ===== Paragraph block =====
   Standalone rows of [heading | content]. Each column is 25% wide and sits at
   its own independent left offset (--para-head-left / --para-content-left,
   0/25/50%) for the editorial look. ≤768px stacks heading above content. */
.paragraph-block { width: 100%; }
.paragraph-row {
  display: flex;
  width: 100%;
  margin-bottom: 28px;
  font-weight: var(--font-body-weight, normal);
}
.paragraph-row:last-child { margin-bottom: 0; }
.paragraph-head {
  position: relative;
  width: 25%;
  left: var(--para-head-left, 0%);
  flex-shrink: 0;
}
.paragraph-content {
  position: relative;
  width: 25%;
  left: var(--para-content-left, 25%);
  min-width: 0;
}
.paragraph-head-text {
  margin: 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight, normal);
  text-transform: var(--text-transform, none);
  font-size: var(--bio-heading-size, var(--heading-size, 14px));
  color: var(--bio-heading-color, var(--heading-color, inherit));
}
.paragraph-head-icon { display: block; width: var(--para-icon-width, 12px); height: auto; opacity: var(--para-icon-opacity, 1); }
.paragraph-content .rows-text,
.paragraph-content .rows-paragraph { margin: 0; font-size: var(--bio-body-size, 14px); line-height: var(--bio-body-line, 1.4); }
.paragraph-content .rows-list,
.paragraph-content .rows-links { list-style: none; margin: 0; padding: 0; }
.paragraph-content .rows-list li,
.paragraph-content .rows-links li { font-size: var(--bio-body-size, 14px); line-height: var(--bio-body-line, 1.4); }
.paragraph-content .rows-link,
.paragraph-content .rows-links a { color: var(--link-color, var(--primary)); text-decoration: var(--accent-deco, none); font-size: var(--bio-body-size, 14px); }
.paragraph-content .rows-link:hover,
.paragraph-content .rows-links a:hover { color: var(--hover-color, var(--secondary)); text-decoration: var(--accent-deco-hover, none); }
@media (max-width: 768px) {
  /* Stack heading above content (like Bio); reset the desktop offsets. */
  .paragraph-row { flex-direction: column; }
  .paragraph-head,
  .paragraph-content { width: 100%; left: 0; }
  .paragraph-head { margin-bottom: 6px; }
}

/* ===== Navbar block (richer header) =====
   Sticky 35px bar with absolutely-pinned branding / search / nav / theme. On
   mobile, nav+search+theme collapse into a hamburger-triggered white overlay. */
.site-navbar {
  position: sticky;
  top: 0;
  z-index: 8;
  width: 100%;
  height: 35px;
  background: var(--background);
  font-size: 13px;
}
.navbar-branding { position: absolute; top: 8px; left: 0px; z-index: 11; color: var(--navbar-branding-color, var(--primary)); text-decoration: var(--accent-deco, none); transition: color 0.15s, text-decoration 0.15s; }
.navbar-branding:hover { color: var(--navbar-branding-hover-color, var(--secondary)); text-decoration: var(--accent-deco-hover, none); }
.navbar-branding .navbar-title {
  margin: 0;
  font-family: var(--navbar-title-font, var(--font-heading));
  font-weight: var(--navbar-title-weight, var(--font-heading-weight, normal));
  font-size: var(--navbar-title-size, 13px);
  text-transform: var(--navbar-title-transform, var(--text-transform, none));
}
.navbar-branding .navbar-logo { display: block; width: var(--navbar-logo-width, 35px); height: auto; }
.navbar-nav { list-style: none; margin: 0; padding: 0; position: absolute; top: 10px; left: 50%; z-index: 9; }
.navbar-nav li { display: inline-block; margin-right: 16px; line-height: var(--navbar-menu-list-line-height, normal); }
.navbar-nav li:last-child { margin-right: 0; }
.navbar-nav a {
  color: var(--link-color, var(--primary));
  text-decoration: var(--accent-deco, none);
  font-size: var(--link-font-size, 13px);
  font-weight: var(--link-font-weight, var(--font-body-weight, normal));
  text-transform: var(--link-transform, var(--text-transform, none));
  line-height: var(--navbar-menu-list-line-height, normal);
}
.navbar-nav a:hover { color: var(--hover-color, var(--secondary)); text-decoration: var(--accent-deco-hover, none); }
.navbar-search { position: absolute; top: 7px; left: 25%; z-index: 9; }
.navbar-search input { background: transparent; border: none; outline: none; color: var(--navbar-search-color, var(--foreground)); font: inherit; font-size: var(--navbar-search-size, 13px); font-weight: var(--font-body-weight, normal); text-transform: var(--navbar-search-transform, var(--text-transform, none)); width: 140px; }
.navbar-search input::placeholder { color: var(--navbar-search-ph-color, #bbb); font-size: var(--navbar-search-ph-size, var(--navbar-search-size, 13px)); font-weight: var(--font-body-weight, normal); text-transform: var(--navbar-search-ph-transform, var(--text-transform, none)); }
.navbar-theme { position: absolute; top: 8px; right: 0px; z-index: 9; }
.navbar-theme button { background: none; border: none; color: var(--navbar-theme-toggle-color, var(--navbar-theme-color, var(--foreground))); font: inherit; font-size: var(--navbar-theme-size, 13px); font-weight: var(--font-body-weight, normal); text-transform: var(--navbar-theme-transform, var(--text-transform, none)); cursor: pointer; padding: 0; }
.navbar-theme button:hover { color: var(--navbar-theme-toggle-hover-color, var(--navbar-theme-toggle-color, var(--foreground))); }
.navbar-theme img { width: var(--navbar-theme-icon-width, 12px); height: auto; vertical-align: middle; }
.navbar-theme .navbar-theme-off { display: none; } /* JS toggles which shows */
.navbar-open, .navbar-close {
  display: none; background: none; border: none; cursor: pointer; padding: 0; line-height: 1;
  color: var(--navbar-menu-label-color, var(--foreground));
  font-size: var(--navbar-menu-label-size, 18px);
  font-weight: var(--navbar-menu-label-weight, var(--font-body-weight, normal));
  text-transform: var(--navbar-menu-label-transform, var(--text-transform, none));
}
.navbar-open {
  color: var(--navbar-open-color, var(--foreground));
}
.navbar-open:hover {
  color: var(--navbar-open-hover-color, var(--navbar-open-color, var(--foreground)));
}
.navbar-close {
  color: var(--navbar-close-color, var(--foreground));
}
.navbar-close:hover {
  color: var(--navbar-close-hover-color, var(--navbar-close-color, var(--foreground)));
}
.navbar-open-icon { width: var(--navbar-open-icon-width, 18px); height: auto; display: block; }
.navbar-close-icon { width: var(--navbar-close-icon-width, 18px); height: auto; display: block; }

/* ===== Mode Navigation (.site-navbar.mode-nav) ==========================
   The navbar in an "overlay-always" layout: the menu index (links + search)
   is hidden behind the Open button on EVERY breakpoint. Reuses every navbar
   class, var, the theme/open-close script, search.html and light/dark colors;
   only the layout + position presets differ. Position vars come from
   modeNavPositionVars(): --modenav-open-left / --modenav-open-right /
   --modenav-list-left / --modenav-search-left. */
.site-navbar.mode-nav .navbar-open {
  display: block; position: absolute; top: 10px;
  left: var(--modenav-open-left, 50%); right: var(--modenav-open-right, auto); z-index: 11;
}
.site-navbar.mode-nav.navbar-menu-open .navbar-open { display: none; }
/* Menu index = full-screen overlay (themed), hidden until Open is clicked. */
.site-navbar.mode-nav .navbar-collapse {
  display: none;
  position: fixed; inset: 0; z-index: 10;
  background: var(--background); color: var(--foreground);
  padding: 60px 16px 72px; overflow-y: auto;
}
.site-navbar.mode-nav.navbar-menu-open .navbar-collapse { display: block; }
/* Close — top-right, only while the overlay is open. */
.site-navbar.mode-nav .navbar-close { display: none; position: fixed; top: 10px; right: 10px; z-index: 12; }
.site-navbar.mode-nav.navbar-menu-open .navbar-close { display: block; }
/* Inside the overlay: menu list (center 50% / left 10px) + search (left 10px /
   center 50%), positioned relative to the fixed .navbar-collapse. */
.site-navbar.mode-nav .navbar-nav { position: absolute; top: 8px; left: var(--modenav-list-left, 50%); }
.site-navbar.mode-nav .navbar-search { position: absolute; top: 3px; left: var(--modenav-search-left, 10px); }
/* Theme toggle sits in the bar (top-right) when closed, above the overlay. */
.site-navbar.mode-nav .navbar-theme { z-index: 12; }
/* Menu list stacks vertically (not inline) inside the overlay, all breakpoints. */
.site-navbar.mode-nav .navbar-nav li { display: block; margin: 0; line-height: var(--navbar-menu-list-line-height, 1.6); }
.site-navbar.mode-nav .navbar-nav a { display: block; line-height: var(--navbar-menu-list-line-height, 1.6); }
/* Desktop open overlay = search + stacked list + close only. The branding
   (which lives in the bar, top-left) would fight the search box, and the theme
   toggle belongs in the overlay only on tablet/mobile — so hide both here. */
@media (min-width: 769px) {
  .site-navbar.mode-nav.navbar-menu-open .navbar-branding,
  .site-navbar.mode-nav.navbar-menu-open .navbar-theme { display: none; }
}

@media (max-width: 768px) {
  /* Mode-nav mobile overlay: list stacked on the left, search bottom-left,
     theme bottom-right when open (top-right in the bar when closed). Open
     button stays centered. Higher specificity than the navbar mobile rules
     below, so these win for .mode-nav. */
  .site-navbar.mode-nav .navbar-open { top: 10px; left: var(--modenav-open-left, 50%); right: var(--modenav-open-right, auto); }
  .site-navbar.mode-nav .navbar-theme { position: absolute; top: 8px; right: 0px; bottom: auto; left: auto; }
  .site-navbar.mode-nav.navbar-menu-open .navbar-theme { position: fixed; top: auto; right: 16px; bottom: 24px; }
  .site-navbar.mode-nav .navbar-nav { position: static; left: auto; top: auto; margin-top: 25px; }
  .site-navbar.mode-nav .navbar-search { position: fixed; left: 16px; bottom: 24px; top: auto; }
}

@media (max-width: 768px) {
  .navbar-open { display: block; position: absolute; top: 8px; right: 0px; z-index: 11; }
  /* Collapse → full-screen overlay (follows the light/dark theme), hidden until
     the hamburger is tapped. */
  .navbar-collapse {
    display: none;
    position: fixed; inset: 0; z-index: 10;
    background: var(--background); color: var(--foreground);
    padding: 60px 16px 72px;
    overflow-y: auto;
  }
  .site-navbar.navbar-menu-open .navbar-collapse { display: block; }
  .site-navbar.navbar-menu-open .navbar-open { display: none; }
  .navbar-close { display: none; position: fixed; top: 8px; right: 10px; z-index: 12; }
  .site-navbar.navbar-menu-open .navbar-close { display: block; }
  /* Links: stacked, breathing room (25px below title/close), 1.6 line-height. */
  .navbar-nav { position: static; left: auto; top: auto; margin-top: 25px; }
  .navbar-nav li { display: block; margin: 0; line-height: var(--navbar-menu-list-line-height, 1.6); }
  .navbar-nav a { display: block; line-height: var(--navbar-menu-list-line-height, 1.6); }
  /* Search bottom-left, theme toggle bottom-right. */
  .navbar-search { position: absolute; left: 16px; bottom: 24px; top: auto; }
  .navbar-search input { width: 60vw; max-width: 240px; }
  .navbar-theme { position: absolute; right: 16px; bottom: 24px; top: auto; left: auto; }
}

/* Functional light/dark theme (navbar toggle). Setting the theme vars on
   body.dark-theme flips the whole site, since all CSS reads var(--background)
   / var(--foreground). */
body.dark-theme {
  --background: #000000;
  --foreground: #fcfcfc;
  --heading-color: #ffffff;
  --primary: #ffffff;
  --secondary: #ffffff;
  --muted: #252525;
}
/* Reflect light/dark on themed surfaces (navbar, index menu, menu links,
   block headings) at ALL breakpoints — !important so it flips even when a
   light-mode color was set inline via a style override. Uses the dark PALETTE
   vars (not hardcoded black/white) so the GENERAL dark colors take effect. */
body.dark-theme .site-navbar { background: var(--background) !important; }
body.dark-theme .navbar-collapse { background: var(--background) !important; color: var(--foreground) !important; }
/* Per-element dark colors (Option 2). Each navbar element reads its own
   dark companion var (set via the panel's dark color picker) and falls back to
   the dark PALETTE default when unset — so a custom dark color wins, otherwise
   the GENERAL dark palette applies. !important so it beats the inline light
   color. */
body.dark-theme .navbar-branding { color: var(--navbar-branding-color-dark, var(--primary)) !important; }
/* Hover companion — without this the !important base rule above defeats the
   light-mode .navbar-branding:hover, so the site title can't change on hover in
   dark mode. Reads the per-element dark hover override, then the light hover
   override, then --secondary (which itself swaps to the dark Accent hover). */
body.dark-theme .navbar-branding:hover { color: var(--navbar-branding-hover-color-dark, var(--navbar-branding-hover-color, var(--secondary))) !important; }
body.dark-theme .navbar-nav a { color: var(--link-color-dark, var(--primary)) !important; }
body.dark-theme .navbar-nav a:hover { color: var(--hover-color-dark, var(--secondary)) !important; }
body.dark-theme .navbar-theme button { color: var(--navbar-theme-toggle-color-dark, var(--navbar-theme-color-dark, var(--foreground))) !important; }
body.dark-theme .navbar-theme button:hover { color: var(--navbar-theme-toggle-hover-color-dark, var(--navbar-theme-toggle-color-dark, var(--foreground))) !important; }
body.dark-theme .navbar-open { color: var(--navbar-open-color-dark, var(--foreground)) !important; }
body.dark-theme .navbar-open:hover { color: var(--navbar-open-hover-color-dark, var(--navbar-open-color-dark, var(--foreground))) !important; }
body.dark-theme .navbar-close { color: var(--navbar-close-color-dark, var(--foreground)) !important; }
body.dark-theme .navbar-close:hover { color: var(--navbar-close-hover-color-dark, var(--navbar-close-color-dark, var(--foreground))) !important; }
body.dark-theme .navbar-search input { color: var(--navbar-search-color-dark, var(--foreground)) !important; }
body.dark-theme .navbar-search input::placeholder { color: var(--navbar-search-ph-color-dark, var(--muted)) !important; }
body.dark-theme .content-col-heading,
body.dark-theme .paragraph-head-text,
body.dark-theme .content-title { color: var(--bio-heading-color-dark, var(--heading-color)) !important; }
body.dark-theme .directory-heading { color: var(--dir-heading-color-dark, var(--heading-color)) !important; }
body.dark-theme .main h1.page-title { color: var(--heading-color) !important; }
/* Per-element dark LINK colors (Option 2) for the existing nav, Bio/Mode,
   Paragraph and Directory blocks. Each reads its own dark companion var (set
   via the panel's "(dark)" picker) and falls back to the dark Accent/Secondary
   palette when unset — so a custom dark link color wins, otherwise links flip
   with the GENERAL dark palette. */
body.dark-theme nav.header-nav a { color: var(--link-color-dark, var(--primary)) !important; }
body.dark-theme nav.header-nav a:hover { color: var(--hover-color-dark, var(--secondary)) !important; }
body.dark-theme .content-col .rows-link,
body.dark-theme .content-col .rows-links a,
body.dark-theme .paragraph-content .rows-link,
body.dark-theme .paragraph-content .rows-links a { color: var(--link-color-dark, var(--primary)) !important; }
body.dark-theme .content-col .rows-link:hover,
body.dark-theme .content-col .rows-links a:hover,
body.dark-theme .paragraph-content .rows-link:hover,
body.dark-theme .paragraph-content .rows-links a:hover { color: var(--hover-color-dark, var(--secondary)) !important; }
body.dark-theme .directory-list li { color: var(--dir-list-color-dark, var(--foreground)) !important; }
body.dark-theme .directory-link,
body.dark-theme .directory-links a { color: var(--dir-link-color-dark, var(--primary)) !important; }
body.dark-theme .directory-link:hover,
body.dark-theme .directory-links a:hover { color: var(--dir-link-hover-color-dark, var(--dir-link-color-dark, var(--secondary))) !important; }

/* ===== Search results page (search.html) ===== */
.search-page { width: 100%; padding: 10px 0; }
.search-page-title { display: none; }
.search-results { display: grid; grid-template-columns: repeat(var(--grid-cols, 2), minmax(0, 1fr)); gap: var(--grid-gap, 16px); width: 100%; }
.search-result-item { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.search-result-image-link { display: block; color: inherit; text-decoration: none; }
.search-result-item .search-result-link.project-title { display: block; color: var(--title-color, var(--primary)); text-decoration: var(--title-decoration, var(--accent-deco, none)); font-size: var(--title-font-size, 13px); padding-left: var(--title-padding-left, 0); text-align: var(--title-align, left); text-transform: var(--text-transform, none); font-weight: var(--font-body-weight, normal); }
.search-result-item .search-result-link.project-title:hover { color: var(--title-hover-color, var(--secondary)); text-decoration: var(--title-decoration-hover, var(--accent-deco-hover, none)); }
.search-result-item img { width: 100%; height: auto; aspect-ratio: var(--img-aspect, auto); object-fit: cover; display: block; }
@media (max-width: 700px) { .search-results { grid-template-columns: 1fr; } }
.search-results .no-search-results-message {
  font-size: var(--navbar-search-size, 13px);
  color: var(--navbar-search-color, var(--foreground));
  text-transform: var(--navbar-search-transform, var(--text-transform, none));
  font-weight: var(--font-body-weight, normal);
}

/* ===== Video block (Media 2c) ===== */
.video-block {
  width: 100%;
  margin: 0;
}
.video-frame {
  position: relative;
  width: 100%;
  background: #000;
  overflow: hidden;
}
/* Embeds (YouTube/Vimeo) get a 16:9 responsive box with an absolutely-filled
   iframe; native uploads size to their own intrinsic ratio. */
.video-frame[data-embed="true"] { padding-top: 56.25%; }
.video-frame[data-embed="true"] .video-embed {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
.video-native { display: block; width: 100%; height: auto; }
.video-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  background: #f2f2f2;
  color: #888;
  font-size: 12px;
  text-align: center;
  padding: 20px;
}
.video-caption {
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.2;
  color: var(--muted, #777);
}

/* ===== Directory grid block =====
   Index-style rows of columns (heading + content). data-cols (2/4/6) drives a
   responsive grid that collapses cleanly: 6 → 3 (tablet) → 2 (mobile),
   4 → 2 → 1, 2 → 2 → 1. */
/* Settings (CSS vars from the block settings) apply block-wide. */
.directory-block {
  width: 100%;
  font-size: var(--dir-font-size, 12px);
  /* No directory-specific weight control: fall back to the GENERAL body weight
     so changing it in the General panel reaches the directory block. */
  font-weight: var(--dir-font-weight, var(--font-body-weight, normal));
}
.directory-row {
  display: grid;
  gap: 28px 36px;
  margin-bottom: 44px;
}
.directory-row:last-child { margin-bottom: 0; }
.directory-row[data-cols="2"] { grid-template-columns: repeat(2, 1fr); }
.directory-row[data-cols="4"] { grid-template-columns: repeat(4, 1fr); }
.directory-row[data-cols="6"] { grid-template-columns: repeat(6, 1fr); }
.directory-cell { min-width: 0; }
.directory-heading {
  margin: 0 0 12px;
  font-size: var(--heading-size, inherit);
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight, inherit);
  color: var(--dir-heading-color, var(--heading-color, var(--foreground)));
}
.directory-text { margin: 0; line-height: 1.2; }
.directory-list,
.directory-links { list-style: none; margin: 0; padding: 0; }
.directory-list li { line-height: var(--dir-list-line, 1.3); }
.directory-links li { line-height: var(--dir-link-line, 1.3); }
/* List text — color + (hover) underline from settings. */
.directory-list li {
  color: var(--dir-list-color, inherit);
  text-decoration: var(--dir-list-deco, none);
}
.directory-list li:hover { text-decoration: var(--dir-list-deco-hover, var(--dir-list-deco, none)); }
/* Links — color + (hover) underline from settings. */
.directory-link,
.directory-links a {
  color: var(--dir-link-color, var(--primary));
  text-decoration: var(--dir-link-deco, var(--accent-deco, none));
  /* Reset the global link sizing (12px / bold) so directory links follow the
     directory block own typography. Text-transform is intentionally NOT reset
     here so the GENERAL/section transform cascade still reaches these links. */
  font-size: inherit;
  font-weight: inherit;
  line-height: var(--dir-link-line, 1.3);
  transition: text-decoration 0.15s ease;
}
.directory-link:hover,
.directory-links a:hover {
  text-decoration: var(--dir-link-deco-hover, var(--accent-deco-hover, none));
  color: var(--dir-link-hover-color, var(--secondary));
}
.directory-empty { color: #666; font-size: 12px; padding: 16px 0; }
@media (max-width: 1024px) {
  .directory-row[data-cols="6"] { grid-template-columns: repeat(3, 1fr); }
  .directory-row[data-cols="4"] { grid-template-columns: repeat(2, 1fr); }
}
/* From 768px down, every directory row sits at 2 columns (6/4/2 all → 2). */
@media (max-width: 768px) {
  .directory-row[data-cols] { grid-template-columns: repeat(2, 1fr); }
}

/* ===== Footer ===== */
.site-footer {
  position: relative;
}

.footer-hero {
  margin-bottom: 15px;
  margin-top: clamp(40px, 12vw, 150px);
}

.footer-hero-image {
  width: 100%;
  height: auto;
  position: relative;
  bottom: -30px;
  left: 0;
  right: 0;
}

.footer-nav {
  z-index: 8;
  position: relative;
}

/* Mobile: 2 columns of social links so labels don't crowd. Tablet+
   restores the original 4-column row below. */
ul.footer-menu-index {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 12px;
  width: 100%;
  position: relative;
  top: 5px;
}

/* ===========================================================================
   Tablet — ≥768px
   =========================================================================== */
@media (min-width: 768px) {
  .wrapper {
    padding-left: 10px;
    padding-right: 10px;
    padding-bottom: 10px;
  }

  /* Tablet+ honors per-page column dial; default 2 if absent. */
  .grid {
    column-count: var(--grid-cols, 2);
    column-gap: var(--grid-gap, 14px);
  }
  .grid > div { margin-bottom: var(--grid-gap, 14px); }

  /* Site description: width from the --desc-width slider (default 33.3%),
     centered on tablet regardless of the desktop alignment preset. */
  .site-description .description-paragraph {
    width: var(--desc-width, 33.3%);
    left: 50%;
  }
  /* Now that the paragraph is narrow, pull the grid up to close the gap. */
  .site-description {
    margin-bottom: -40px;
  }

  /* Studio: image left, text stacked right. Half-and-half split. */
  .page-content {
    grid-template-columns: 1fr 1fr;
    gap: 0px;
  }
  /* Inner content (heading | paragraph) goes two-column from tablet up, not
     just desktop — otherwise Bio/About's right column stacks oddly between
     769px and 1023px. Matches the @media (min-width: 1024px) rule below. */
  .page-content .content {
    grid-template-columns: 1fr 1fr;
    gap: 0px;
  }
  /* image_position=right (4f.8): swap the column order so the image lands
     in the second column. Children explicitly assigned so we don't rely
     on grid-auto-flow ordering. */
  .page-content[data-image-position="right"] {
    grid-template-columns: 1fr 1fr;
  }
  .page-content[data-image-position="right"] .content-image { order: 2; }
  .page-content[data-image-position="right"] .content       { order: 1; }

  ul.footer-menu-index {
    grid-template-columns: repeat(4, 1fr);
    gap: 14px;
  }

  .main h1.page-title {
    font-size: var(--heading-size, 24px);
  }
}

/* ===========================================================================
   Desktop — ≥1024px (restores the original editorial design)
   =========================================================================== */
@media (min-width: 1024px) {
  .site-header {
    height: 35px;
    min-height: 0;
  }

  ul.header-menu-index {
    flex-wrap: nowrap;
  }

  .grid {
    column-gap: var(--grid-gap, 16px);
  }
  .grid > div { margin-bottom: var(--grid-gap, 16px); }

  /* Site description: width from the --desc-width slider (default 33.3%) +
     honor the per-page alignment preset (--desc-left: a=0% / b=25% / c=50%). */
  .site-description .description-paragraph {
    width: var(--desc-width, 33.3%);
    left: var(--desc-left, 50%);
  }

  /* Studio desktop: nested grid recreates the original 50/25/25 — image
     in the left half, title + paragraph each occupy ~25% in the right half. */
  .page-content {
    grid-template-columns: 1fr 1fr;
    gap: 0px;
  }
  .page-content .content {
    grid-template-columns: 1fr 1fr;
    gap: 0px;
  }

  ul.footer-menu-index {
    gap: 16px;
  }

  .main h1.page-title {
    font-size: var(--heading-size, 28px);
  }
}
