/* ==========================================================================
   Jacob Bixenman — Director / Creative Director
   Design system: paper-toned editorial minimalism.
   Display: Fraunces (serif, optical sizing) — Sans: Inter (ui/body)
   ========================================================================== */

@import url('https://fonts.googleapis.com/css2?family=Geist:wght@400;500;600;700;800&family=Geist+Mono:wght@400;500;600&display=swap');

:root{
  /* -- color: stark white, neutral greys -- */
  --color-bg: #FFFFFF;
  --color-bg-raised: #FFFFFF;
  --color-ink: #14130F;
  --color-ink-soft: #5B584F;
  --color-ink-faint: #9A9A9A;
  --color-line: #EEEEEE;
  --color-line-strong: #CFCFCF;
  --color-accent: #14130F;

  /* -- type -- */
  --font-display: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-sans: 'Geist', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-mono: 'Geist Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --fs-hero: clamp(1.375rem, 2.2vw, 1.875rem);
  --fs-xl: clamp(1.125rem, 1.4vw, 1.375rem);
  --fs-lg: clamp(1rem, 1.1vw, 1.125rem);
  --fs-md: 0.9375rem;
  --fs-body: 0.8125rem;
  --fs-sm: 0.75rem;
  --fs-xs: 0.6875rem;

  /* -- spacing scale (4/8pt rhythm) -- */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2.5rem;
  --sp-7: 4rem;
  --sp-8: 6rem;
  --sp-9: 9rem;
  --sp-10: 13rem;

  --container-max: 1440px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 250ms;
  --dur-med: 500ms;
  --dur-slow: 900ms;

  --nav-h: 64px;
  color-scheme: light;
}

/* -- reset -- */
*, *::before, *::after{ box-sizing: border-box; }
html{
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  *, *::before, *::after{
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
}
body{
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100dvh;
  padding-bottom: var(--nav-h);
}
img, video{ max-width: 100%; display: block; }
a{ color: inherit; text-decoration: none; }
ul{ list-style: none; margin: 0; padding: 0; }
h1,h2,h3,h4,p{ margin: 0; }
button{ font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; }
input, textarea{ font: inherit; color: inherit; }

::selection{ background: var(--color-accent); color: var(--color-bg-raised); }

:focus-visible{
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

/* -- utility -- */
.container{
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.visually-hidden{
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.eyebrow{
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}
.font-display{ font-family: var(--font-display); }

/* -- skip link -- */
.skip-link{
  position: fixed;
  top: -60px; left: var(--sp-4);
  z-index: 200;
  background: var(--color-ink);
  color: var(--color-bg);
  padding: var(--sp-3) var(--sp-5);
  font-size: var(--fs-sm);
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus{ top: var(--sp-4); }

/* ==========================================================================
   Nav
   ========================================================================== */
.site-header{
  position: fixed;
  bottom: 0; left: 0; right: 0;
  z-index: 100;
  height: var(--nav-h);
  display: flex;
  align-items: center;
  background: transparent;
}
@media (max-width: 899px){
  .site-header{
    background: var(--color-bg);
  }
}

.nav-inner{
  width: 100%;
  max-width: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}
.nav-mark{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

/* -- nav menu: an asterisk that transforms into inline links -- */
.nav-menu{
  position: relative;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-shrink: 0;
}
.nav-asterisk{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  line-height: 1.5;
  color: var(--color-ink);
  cursor: pointer;
  transition: opacity var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.nav-menu.is-open .nav-asterisk{
  opacity: 0;
  pointer-events: none;
}
/* Contact swaps into the asterisk's own spot, on nav-mark's line, instead
   of joining the dropdown — so it stays flush with "Jacob Bixenman"
   always, open or closed. */
.nav-inline-link{
  position: absolute;
  top: 50%; right: 0;
  transform: translateY(-50%);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  color: var(--color-ink);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.nav-menu.is-open .nav-inline-link{
  opacity: 1;
  pointer-events: auto;
}
.nav-menu-links{
  position: fixed;
  z-index: 100;
  /* dips into the header bar's own empty upper margin — nav-mark sits
     centered in that bar, well below this edge, so nothing gets covered —
     to match this panel's own line spacing instead of stopping at the
     bar's outer edge and leaving extra air above the last link */
  bottom: calc((var(--nav-h) - 1.5 * var(--fs-sm)) / 2);   /* last link sits on the name's line */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: var(--sp-2);
  opacity: 0;
  transform: translateY(8px);
  pointer-events: none;
  transition: opacity var(--dur-med) var(--ease-out), transform var(--dur-med) var(--ease-out);
}
.nav-menu.is-open .nav-menu-links{
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
/* mobile: one continuous full-width panel docked directly above the header
   bar — not a chip floating over each line — so opening the menu reads as
   a single block growing from the same edge as the name's own background,
   not a separate shape rising above it. Fixed (not relative to .nav-menu)
   so it doesn't depend on that box's own size for placement. */
@media (max-width: 899px){
  .nav-menu-links{
    left: 0; right: 0;
    padding-top: var(--sp-2);
    padding-inline: var(--gutter);
    background: var(--color-bg);
  }
}
/* desktop: the header bar itself stays transparent here (masking isn't
   needed at this width), so the dropdown stays a small right-aligned
   block instead of a page-wide bar cutting across unrelated content */
@media (min-width: 900px){
  .nav-menu-links{
    right: var(--gutter);
  }
}
.nav-menu-links a{
  display: block;
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--color-ink);
  white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-out);
}

/* ==========================================================================
   Buttons / links
   ========================================================================== */
.btn{
  display: inline-flex;
  align-items: baseline;
  gap: var(--sp-2);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  color: var(--color-ink-soft);
  border-bottom: 1px solid var(--color-line-strong);
  padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}
.btn:hover{ color: var(--color-ink); border-color: var(--color-ink); }
.btn-icon{ transition: transform var(--dur-fast) var(--ease-out); }
.btn:hover .btn-icon{ transform: translateX(3px); }

.about-link{
  color: var(--color-ink);
}

/* ==========================================================================
   Reveal-on-scroll
   ========================================================================== */
.reveal{
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--dur-slow) var(--ease-out), transform var(--dur-slow) var(--ease-out);
}
.reveal.is-visible{ opacity: 1; transform: translateY(0); }
.reveal-stagger > *{ transition-delay: calc(var(--i, 0) * 70ms); }

/* ==========================================================================
   Hero (landing) — a single centered image, nothing else
   ========================================================================== */
.hero-visual{
  min-height: calc(100dvh - var(--nav-h));
  display: flex;
  align-items: center;
  justify-content: center;
  padding-block: var(--sp-7);
}
.hero-image{
  display: flex;
  align-items: center;
  justify-content: center;
  /* an invisible square stage: it never changes size, so the stills (all
     different shapes) are centered in the same spot and nothing jumps */
  --stage: min(375px, 58.1vw);   /* 25% larger than the previous 300px / 46.5vw */
  width: var(--stage);
  height: var(--stage);   /* explicit, so the images' max-height:100% always resolves */
}
/* Each still is sized by its own proportions (auto width/height, capped to
   the stage) rather than stretched to fill it, so the black border sits
   right on the photo's edge instead of around an empty letterbox. */
.hero-image img{
  display: block;
  width: auto; height: auto;
  max-width: 100%; max-height: 100%;
  /* the warm gray the tile used to be: the page color mixed 8% toward black */
  border: 5pt solid color-mix(in srgb, var(--color-bg) 92%, #000);
}
/* until the first still is set there's no src — don't show the broken-image
   box and alt text */
.hero-image img:not([src]){ visibility: hidden; }

/* ==========================================================================
   Section framing
   ========================================================================== */
.section{ padding-block: var(--sp-8); }
.section-head-row{
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--sp-5);
  flex-wrap: wrap;
}
.section-count{
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--color-ink-soft);
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   Work grid
   ========================================================================== */
/* lets the grid spread across very wide windows instead of stopping at
   .container's shared 1440px cap — same fix as .nav-inner needed */
.work-section{
  max-width: none;
  padding-top: var(--sp-6);
  padding-bottom: var(--sp-6);
}
@media (min-width: 900px){
  .work-section{
    padding-top: var(--sp-7);
    padding-bottom: var(--sp-7);
  }
}
/* shown only when the grid is narrowed to one client (?client=) */
.work-filter{
  display: flex;
  justify-content: center;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
}
.work-filter[hidden]{ display: none; }
.work-filter a{
  color: var(--color-ink-faint);
  transition: color var(--dur-fast) var(--ease-out);
}
.work-filter a:hover{ color: var(--color-ink); }
.work-grid{
  display: grid;
  grid-template-columns: repeat(1, minmax(0, 176px));
  justify-content: center;
  align-items: center;
  row-gap: clamp(3rem, 8vw, 8rem);
  column-gap: clamp(2.5rem, 6vw, 5rem);
}
/* column counts step up as soon as the next column fits (tablets included),
   not at device-class breakpoints — 3 fit from ~700px, 4 from ~1200px */
@media (min-width: 620px){
  .work-grid{ grid-template-columns: repeat(2, minmax(0, 176px)); }
}
@media (min-width: 700px){
  .work-grid{ grid-template-columns: repeat(3, minmax(0, 176px)); }
}
@media (min-width: 900px){
  .work-grid{
    justify-content: space-evenly;
    margin-inline: clamp(2.5rem, 6vw, 5rem);
    row-gap: clamp(5rem, 11vw, 11rem);
  }
}
@media (min-width: 1200px){
  .work-grid{ grid-template-columns: repeat(4, minmax(0, 176px)); }
}
/* narrowed to a single client with only 1–2 projects (set by work.js) */
.work-grid[data-count]{ justify-content: center; margin-inline: 0; }
.work-grid[data-count="1"]{ grid-template-columns: minmax(0, 176px); }
@media (min-width: 620px){
  .work-grid[data-count="2"]{ grid-template-columns: repeat(2, minmax(0, 176px)); }
}
.work-card{
  display: block;
  width: 100%;
}
.work-card-frame{
  position: relative;
  overflow: hidden;
  background: var(--color-line);
}
.work-card-frame img{
  width: 100%; height: auto; display: block;
  filter: grayscale(0.08);
  transition: filter var(--dur-med) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
.work-card:hover .work-card-frame img{ filter: grayscale(0); }

.work-card-caption{
  margin-top: var(--sp-3);
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
  gap: var(--sp-3);
}
.work-card-meta{
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
}
.work-card-meta dd{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  line-height: 1.2;
  letter-spacing: 0.01em;
  margin: 0;
}
.work-card-num{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  color: var(--color-ink);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.work-item{ transition: opacity var(--dur-fast) var(--ease-out); }

/* ==========================================================================
   About
   ========================================================================== */
.about-minimal{
  min-height: calc(100dvh - var(--nav-h));
  display: flex;
  align-items: center;
  justify-content: center;
}
.about-minimal-inner{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-5);
  text-align: left;
}
.about-minimal-text{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  line-height: 1.6;
  letter-spacing: 0.01em;
}
.about-bio-text{
  max-width: 34rem;
}
.about-links{
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--sp-3);
}
/* "Clients Include:" — a plain stacked list directly under the bio */
.about-clients-list{
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Selected Press / Selected Clients sit side by side so each one's list
   drops into the empty space below instead of covering the other's label;
   they share a `name`, so opening one closes the other */
.about-disclosures{
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  column-gap: var(--sp-5);
}
.about-press{
  /* the dropdown is taken out of flow (position:absolute below) so opening
     it never changes this element's own height — otherwise the bio and
     links above would shift each time, since the whole block is centered
     vertically as a group */
  position: relative;
}
.about-press summary{
  cursor: pointer;
  list-style: none;
}
.about-press summary::-webkit-details-marker{ display: none; }
.press-list{
  position: absolute;
  top: 100%;
  left: 0;
  /* absolutely positioned with no explicit width, this would shrink-wrap
     to an oddly narrow guess and wrap article titles word-by-word —
     give it real room to breathe, capped so it can't overflow on mobile */
  width: min(22rem, calc(100vw - var(--gutter) * 2));
  margin: 0;
  margin-top: var(--sp-3);
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* client names are short — size the list to them rather than the 22rem the
   press titles need, which would run off a phone screen from the 2nd column */
.press-list.client-list{ width: max-content; max-width: calc(100vw - var(--gutter) * 2); }

/* ==========================================================================
   Project detail
   ========================================================================== */
.project-hero{ padding-top: var(--sp-6); }   /* breathing room above the details on narrow screens */
@media (min-width: 860px){
  /* on desktop .project-split's own padding-top (var(--sp-6)) already lines
     the imagery up with the fixed info panel's top — no extra needed */
  .project-hero{ padding-top: 0; }
}
@media (min-width: 900px){
  /* matches the Projects grid's effective left edge — its own margin-inline
     plus the extra leading gap that `justify-content: space-evenly` adds */
  /* padding, not margin: this element is width:100% inside .container, so
     a non-auto margin-inline on top of that over-constrains the box and
     causes horizontal overflow. Padding stays inside the box (box-sizing:
     border-box), so it can't push the page wider. */
  .project-hero{ padding-inline: clamp(3rem, calc(25vw - 6.75rem), 15.75rem); }
}

/* -- split layout: images stack and scroll past a pinned info column -- */
.project-split{
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-7);
  /* splits the difference between the original --sp-8 (96px) and the
     tighter --sp-5 (24px) mobile once used here */
  padding-block: var(--sp-6) calc((var(--sp-8) + var(--sp-5)) / 2);
}
.project-images{
  display: flex;
  flex-direction: column;
  gap: var(--sp-6);
}
.project-images img{
  width: 100%;
  height: auto;
  display: block;
  background: var(--color-line);
}
.project-images .is-video{
  width: 100%;
  aspect-ratio: 16/9;
  background: var(--color-bg);
}
.project-images iframe{ width: 100%; height: 100%; border: 0; display: block; background: var(--color-bg); }

/* every text element in this panel shares one size/weight/tracking —
   only spacing between blocks establishes hierarchy, not type scale */
.project-info h1,
.project-meta-list dt,
.project-meta-list dd{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  line-height: 1.2;
  letter-spacing: 0.01em;
}
.project-meta-groups{
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.project-meta-list{ margin: 0; }
.project-meta-list dt{ color: var(--color-ink-faint); }
.project-meta-list dd{ margin: 0; }

@media (max-width: 859px){
  .project-split{ gap: var(--sp-5); padding-top: var(--sp-2); }
  .project-info{ order: -1; }
}

@media (min-width: 860px){
  .project-split{
    grid-template-columns: 1.15fr 0.85fr;
    align-items: start;
    gap: var(--sp-6);
  }
  .project-info{
    /* position/left/width/top/max-height are all set in JS as position:fixed
       so the panel never moves on scroll — only the imagery does. Fixed
       positioning takes it out of this grid, so its column geometry has to
       be measured and re-applied explicitly (see pinInfoPanel in project.js). */
    overflow-y: auto;
    padding-bottom: var(--sp-4);
  }
}

/* ==========================================================================
   Work view switch (Grid / List) — fixed top right, both words always shown,
   the active one underlined
   ========================================================================== */
.work-view{
  position: fixed;
  top: 0; right: 0;
  z-index: 90;
  display: flex;
  gap: var(--sp-4);
  height: var(--nav-h);
  align-items: center;
  padding-inline: var(--gutter);
}
.work-view button{
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  letter-spacing: 0.01em;
  color: var(--color-ink-faint);
  cursor: pointer;
}
.work-view button[aria-pressed="true"]{
  color: var(--color-ink);
  text-decoration: underline;
  text-underline-offset: 0.35em;
  text-decoration-thickness: 1px;
}
/* phones: a strip across the top so images don't slide under the words */
@media (max-width: 899px){
  .work-view{ left: 0; background: var(--color-bg); justify-content: flex-end; }
}
/* ==========================================================================
   Work card text (Index mode) — same card, same position; swaps in for
   the image instead of navigating to a separate list layout
   ========================================================================== */
.work-card-text{
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-1);
  padding: var(--sp-4);
  background: var(--color-bg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
  font-family: var(--font-mono);
  font-weight: 500;
  font-size: var(--fs-sm);
  line-height: 1.3;
  letter-spacing: 0.01em;
  color: var(--color-ink);
}
.work-grid.is-index-mode .work-card-frame{ background: none; }
.work-grid.is-index-mode .work-card-frame img{ opacity: 0; }
.work-grid.is-index-mode .work-card-text{
  opacity: 1;
  pointer-events: auto;
}

/* ==========================================================================
   Page enter fade
   ========================================================================== */
body{ animation: pageIn 600ms var(--ease-out) both; }
@keyframes pageIn{
  from{ opacity: 0; }
  to{ opacity: 1; }
}

/* ==========================================================================
   Phones: landing images and Projects cards a bit larger (about 25%)
   ========================================================================== */
@media (max-width: 619px){
  .hero-image{ --stage: min(420px, 72.6vw); }
  .work-grid,
  .work-grid[data-count="1"]{ grid-template-columns: repeat(1, minmax(0, 220px)); }
}

/* ==========================================================================
   Phones: the name / Menu bar sits at the top of the page (the menu drops
   down from it) and Grid / List takes the bottom edge — desktop is unchanged
   ========================================================================== */
@media (max-width: 899px){
  body{ padding-top: var(--nav-h); padding-bottom: 0; }
  body:has(.work-view){ padding-bottom: var(--nav-h); }
  /* the dropdown is one full-width block that starts at the very top and
     paints behind the bar's own text, so the name and the first link share
     a line and the whole strip has one continuous background */
  .site-header{ top: 0; bottom: auto; z-index: 101; transition: background-color var(--dur-med) var(--ease-out); }
  body:has(.nav-menu.is-open) .site-header{ background: transparent; pointer-events: none; }
  /* the dropdown lives inside the header, so lift the name above it */
  .nav-mark{ position: relative; z-index: 101; }
  body:has(.nav-menu.is-open) .nav-mark{ pointer-events: auto; }
  .nav-menu-links{
    bottom: auto;
    top: 0;
    left: 0;
    right: 0;
    /* first link sits on the name's line */
    padding: calc((var(--nav-h) - 1.5 * var(--fs-sm)) / 2) var(--gutter) var(--sp-2);
    transform: translateY(-8px);
  }
  .nav-menu.is-open .nav-menu-links{ transform: translateY(0); }
  .work-view{ top: auto; bottom: 0; justify-content: center; }
}

/* ==========================================================================
   Landing page: the image stage is centred on the screen itself, not on
   whatever is left after the fixed bar — the bar overlays the page, so it
   takes no room (same at the top on phones and at the bottom on desktop)
   ========================================================================== */
body:has(.hero-visual){ padding-top: 0; padding-bottom: 0; }
.hero-visual{ min-height: 100vh; min-height: 100dvh; }

/* never taller than the room between the bar's own height above and below —
   on a short screen (a phone on its side) the image shrinks to fit and
   stays centred instead of running under the bar or off the screen */
.hero-image{ --stage: min(375px, 58.1vw, calc(100vh - 2 * var(--nav-h)), calc(100dvh - 2 * var(--nav-h))); }
@media (max-width: 619px){
  .hero-image{ --stage: min(420px, 72.6vw, calc(100vh - 2 * var(--nav-h)), calc(100dvh - 2 * var(--nav-h))); }
}

/* ==========================================================================
   About page: the text block is centred on the screen itself — the fixed
   bar overlays the page and takes no room (top on phones, bottom on desktop)
   ========================================================================== */
body:has(.about-minimal){ padding-top: 0; padding-bottom: 0; }
.about-minimal{ min-height: 100vh; min-height: 100dvh; }
/* equal room for the bar above and below keeps the block centred while
   guaranteeing it never slides under the bar on a short screen (a phone on
   its side, or with larger text) */
.about-minimal{ padding-block: var(--nav-h); }
