/* johannahauterville.com */

:root {
  --bg: #0c0b0a;
  --raise: #141210;
  --ink: #ece7df;
  --muted: #a79f95;
  --faint: #8a8277;
  --rule: #24211d;
  --hair: #1a1815;
  --accent: #d9a441;
  --accent-hi: #f0c069;
  --serif: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; scroll-padding-top: 88px; }
/* 88px clears the sticky bar at every width: 72px on desktop, 73px on a
   phone now the burger keeps the nav to a single row. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 300;
  font-size: 16px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hi); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.wrap { max-width: 1240px; margin: 0 auto; padding: 0 clamp(20px, 5vw, 72px); }
.skip {
  position: absolute; left: -9999px; top: 0; background: var(--accent); color: var(--bg);
  padding: 10px 18px; font-family: var(--mono); font-size: 13px; z-index: 50;
}
.skip:focus { left: 12px; top: 12px; }
.eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--accent);
}

/* ---------- nav ---------- */
.topbar {
  position: sticky; top: 0; z-index: 40;
  background: rgba(12, 11, 10, .88);
  -webkit-backdrop-filter: saturate(160%) blur(10px);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--rule);
}
@supports not (backdrop-filter: blur(10px)) { .topbar { background: var(--bg); } }
.nav {
  display: flex; justify-content: space-between; align-items: center; gap: 20px;
  /* vertical only: .nav shares its element with .wrap, and the padding
     shorthand here would wipe out .wrap's horizontal inset. */
  padding-top: 18px; padding-bottom: 18px; flex-wrap: wrap;
}
.nav .name { font-family: var(--serif); font-size: 21px; color: var(--ink); }
.nav ul { display: flex; gap: clamp(18px, 3vw, 36px); list-style: none; margin: 0; padding: 0; }
.nav li a {
  font-family: var(--mono); font-size: 12px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint);
  /* a label that breaks across two lines reads as a fault, not a wrap:
     let the row wrap instead, and keep every label intact */
  white-space: nowrap;
}
.nav li a:hover { color: var(--ink); }
.nav li:last-child a { color: var(--accent); }

/* The reel comes straight after the headline, at every width. The bio and
   the facts follow it: nobody arriving at a video editor's site should have
   to read half a screen of prose before seeing a frame of video.
   :not(.nav) because the nav shares the .wrap class and must stay a row. */
.wrap:not(.nav) { display: flex; flex-direction: column; }
.hero  { order: 1; }
.reel  { order: 2; }
.about { order: 3; }
main   { order: 4; }
.cta   { order: 5; }
.foot  { order: 6; }

/* ---------- hero ---------- */
.hero { padding: clamp(48px, 7vw, 88px) 0 0 0; }
.hero h1 {
  font-family: var(--serif); font-weight: 400;
  font-size: clamp(40px, 7.2vw, 92px); line-height: 1.0; letter-spacing: -.015em;
  margin: 0; max-width: 14ch; text-wrap: balance;
}
.hero h1 em { font-style: italic; color: var(--accent); }
/* The portrait sits inside the bio with the text running around it, so the
   hero stays short and the reel arrives sooner. The soft edge is baked into
   the image's alpha, so no border, radius or crop here: any hard edge would
   fight it. */
.portrait {
  float: left;
  --portrait-size: clamp(102px, 13.6vw, 160px);
  width: var(--portrait-size); height: var(--portrait-size);
  object-fit: cover; filter: grayscale(.12);
  /* box flush with the text column and the top of the copy: the feathered
     edge is left to bleed past both, which is the point of it */
  margin: 0;
}
/* the third paragraph always starts below the photo, so the text never
   breaks out from behind it mid-thought */
.bio p:nth-of-type(3) { clear: left; }

.about { margin-top: clamp(60px, 8vw, 96px); }
.hero-cols { display: grid; grid-template-columns: 1fr; gap: 40px; }
@media (min-width: 900px) { .hero-cols { grid-template-columns: 1.15fr 1fr; gap: 72px; } }
.bio p { color: var(--muted); margin: 0 0 15px 0; max-width: 60ch; font-size: 16.5px; }
.bio p:last-child { margin-bottom: 0; }
.side { align-self: start; }
.facts { margin: 0; }
.fact {
  display: flex; justify-content: space-between; gap: 24px; align-items: baseline;
  padding: 13px 0; border-top: 1px solid var(--rule);
  font-family: var(--mono); font-size: 13px;
}
.fact:last-of-type { border-bottom: 1px solid var(--rule); }
.fact dt { color: var(--faint); flex-shrink: 0; }
.fact dd { margin: 0; text-align: right; color: var(--ink); }
.fact.live dd { color: var(--accent); }
.fact dd a {
  color: var(--ink);
  /* underlined so they read as links rather than plain labels */
  text-decoration: underline;
  text-decoration-color: var(--faint);
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}
.fact dd a + a { margin-left: 14px; }
.fact dd a:hover { color: var(--accent); text-decoration-color: var(--accent); }

.past { margin-top: 26px; }
.past .lbl {
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--faint);
}
.past ul {
  list-style: none; margin: 12px 0 0 0; padding: 0;
  display: flex; flex-wrap: wrap; gap: 6px 10px;
  font-family: var(--mono); font-size: 12.5px; color: var(--muted); line-height: 1.5;
}
.past li:not(:last-child)::after { content: " -"; color: var(--faint); }

/* ---------- scroll cues ---------- */
.jump {
  display: flex; flex-direction: column; align-items: center; gap: 9px;
  margin: clamp(34px, 5vw, 54px) auto 0 auto; width: max-content;
  font-family: var(--mono); font-size: 11px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--faint);
}
.jump:hover { color: var(--accent); }
.jump svg { animation: nudge 2.4s ease-in-out infinite; }
@keyframes nudge {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(5px); }
}

/* ---------- players ---------- */
.player {
  position: relative; display: block; width: 100%; padding: 0; border: 0;
  background: #000; overflow: hidden; cursor: pointer; color: inherit;
  aspect-ratio: 16 / 9;
}
.player.vertical { aspect-ratio: 9 / 16; }
.player img { width: 100%; height: 100%; object-fit: cover; }
.player .veil {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(12,11,10,.55), rgba(12,11,10,0) 55%);
  transition: background .25s ease;
}
.player:hover .veil { background: linear-gradient(to top, rgba(12,11,10,.35), rgba(12,11,10,0) 62%); }
.player .btn {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
  pointer-events: none; transition: transform .25s ease;
}
.player:hover .btn { transform: translate(-50%,-50%) scale(1.07); }
.player .stamp {
  position: absolute; left: 22px; bottom: 18px; pointer-events: none;
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink);
}
.player iframe, .embed iframe { width: 100%; height: 100%; border: 0; display: block; }

/* A playing video needs its own way out. YouTube fades its controls after a
   few seconds, which otherwise leaves it running with nothing to stop it. */
.player.playing { cursor: default; }
.stop {
  position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
  padding: 0; cursor: pointer; border: 1px solid var(--rule);
  background: rgba(12, 11, 10, .72); color: var(--ink);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; transition: opacity .2s ease, border-color .2s ease, color .2s ease;
}
.player.playing:hover .stop,
.stop:focus-visible { opacity: 1; }
.stop:hover { border-color: var(--accent); color: var(--accent); }
/* no hover on touch, so keep it permanently visible there */
@media (hover: none) { .stop { opacity: 1; } }
.embed { position: relative; aspect-ratio: 16 / 9; background: var(--raise); border: 1px solid var(--rule); }

/* ---------- reel ---------- */
.reel { padding: clamp(44px, 6vw, 72px) 0 0 0; }

/* ---------- section heads ---------- */
.sechead {
  display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap;
  border-bottom: 1px solid var(--rule); padding-bottom: 18px;
  margin-top: clamp(70px, 9vw, 116px);
}
.sechead h2 { font-family: var(--serif); font-weight: 400; font-size: clamp(26px, 3.4vw, 34px); margin: 0; }
.sechead .count {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--faint); margin-left: auto;
}

/* ---------- work ---------- */
.piece {
  display: grid; grid-template-columns: 1fr; gap: 26px;
  padding: clamp(34px, 5vw, 56px) 0; border-bottom: 1px solid var(--hair);
}
@media (min-width: 940px) { .piece { grid-template-columns: 1.75fr 1fr; gap: 52px; align-items: start; } }
.piece .num { font-family: var(--mono); font-size: 11.5px; letter-spacing: .13em; color: var(--accent); }
.piece h3 {
  font-family: var(--serif); font-weight: 400; font-size: clamp(26px, 3vw, 34px);
  line-height: 1.12; margin: 12px 0 0 0;
}
.piece .meta > p { color: var(--muted); margin: 14px 0 0 0; font-size: 15.5px; }
.tags { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 20px; list-style: none; padding: 0; }
.tags li {
  font-family: var(--mono); font-size: 11px; letter-spacing: .05em; color: var(--faint);
  border: 1px solid var(--rule); padding: 6px 11px;
}

/* ---------- shorts ---------- */
/* Two per row on wide screens, thumbnail beside its text so a short row
   still reads as a full block. auto-fit, not auto-fill: empty tracks
   collapse instead of leaving a gap where the next short would go. */
.shorts {
  display: grid;
  /* min() so the track can shrink below 400px on a narrow phone;
     a bare minmax(400px, 1fr) overflows any viewport under 400px. */
  grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr));
  gap: clamp(24px, 3vw, 40px); margin-top: 38px; list-style: none; padding: 0;
}
.short { display: grid; grid-template-columns: 132px 1fr; gap: 22px; align-items: start; }
.short h3 { font-family: var(--sans); font-weight: 400; font-size: 16px; margin: 0; }
.short .lbl {
  font-family: var(--mono); font-size: 11px; color: var(--faint);
  margin: 6px 0 0 0; line-height: 1.5; text-transform: uppercase; letter-spacing: .08em;
}
.short p.body { color: var(--muted); font-size: 14.5px; margin: 12px 0 0 0; line-height: 1.62; }
@media (max-width: 420px) {
  .short { grid-template-columns: 104px 1fr; gap: 16px; }
}

/* ---------- lightbox (vertical shorts) ---------- */
.lightbox {
  position: fixed; inset: 0; z-index: 100;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(8, 7, 6, .93);
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  animation: lb-in .18s ease-out;
}
@keyframes lb-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .lightbox { animation: none; } }
.lb-frame {
  /* width comes from whichever is smaller: the viewport, or what a 9:16
     frame can be while still fitting the height. */
  width: min(calc(100vw - 40px), calc(86vh * 9 / 16));
  aspect-ratio: 9 / 16;
  background: #000; box-shadow: 0 24px 80px rgba(0, 0, 0, .6);
}
/* dvh tracks the visible area as a phone's toolbars slide away; plain vh
   measures the largest viewport, so the frame can sit under the browser
   chrome on iOS. vh above stays as the fallback. */
@supports (height: 100dvh) {
  .lb-frame { width: min(calc(100vw - 40px), calc(86dvh * 9 / 16)); }
}
.lb-frame iframe { width: 100%; height: 100%; border: 0; display: block; }
.lightbox .lb-close {
  position: absolute; top: 18px; right: 18px; opacity: 1;
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  background: transparent; border: 1px solid var(--rule); color: var(--ink);
  cursor: pointer; padding: 0;
  transition: border-color .2s ease, color .2s ease;
}
.lightbox .lb-close:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- private collection pages ---------- */
.collection-hero { padding-bottom: 0; }
.collection-hero h1 { font-size: clamp(34px, 5.2vw, 62px); max-width: 18ch; margin-top: 16px; }
.collection-intro {
  color: var(--muted); font-size: 16.5px; max-width: 58ch; margin: 22px 0 0 0;
}
.collection .piece:first-of-type { border-top: 1px solid var(--rule); margin-top: clamp(44px, 6vw, 72px); }
/* a vertical short in a collection: don't let it stretch to the full
   column, and centre it under the landscape videos above it */
.collection .piece.upright .player { max-width: 300px; margin-inline: auto; }
@media (min-width: 940px) { .collection .piece.upright { grid-template-columns: 1.75fr 1fr; } }
.topbar .name { font-family: var(--serif); font-size: 21px; color: var(--ink); }
.count-plain {
  font-family: var(--mono); font-size: 12px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--faint);
}

/* ---------- cta ---------- */
.cta {
  margin-top: clamp(70px, 9vw, 116px); border-top: 1px solid var(--rule);
  padding: clamp(48px, 7vw, 90px) 0 clamp(60px, 9vw, 100px) 0;
}
.cta .big {
  font-family: var(--serif); font-weight: 400; font-size: clamp(26px, 4vw, 46px);
  line-height: 1.2; margin: 0; max-width: 24ch; text-wrap: pretty;
}
.cta .big em { font-style: italic; color: var(--accent); }
.cta .sub {
  color: var(--ink); margin: 26px 0 0 0;
  font-family: var(--serif); font-size: clamp(22px, 2.8vw, 32px);
  line-height: 1.25;
}
.go {
  display: inline-block; margin-top: 30px; border: 1px solid var(--accent); color: var(--accent);
  padding: 15px 34px; font-family: var(--mono); font-size: 12.5px;
  letter-spacing: .11em; text-transform: uppercase;
  transition: background .2s ease, color .2s ease;
}
.go:hover { background: var(--accent); color: var(--bg); }

/* ---------- contact form ---------- */
.form { margin-top: 34px; max-width: 560px; display: grid; gap: 16px; }
.form label { font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--faint); }
.form input, .form textarea {
  width: 100%; background: var(--raise); border: 1px solid var(--rule); color: var(--ink);
  font-family: var(--sans); font-size: 16px; padding: 12px 14px; border-radius: 0;
}
.form input:focus, .form textarea:focus { border-color: var(--accent); outline: none; }
.form textarea { min-height: 140px; resize: vertical; }
.form button {
  justify-self: start; cursor: pointer; background: transparent;
  border: 1px solid var(--accent); color: var(--accent);
  padding: 15px 34px; font-family: var(--mono); font-size: 12.5px;
  letter-spacing: .11em; text-transform: uppercase;
  transition: background .2s ease, color .2s ease;
}
.form button:hover { background: var(--accent); color: var(--bg); }
.hp { position: absolute; left: -9999px; }

/* ---------- after the form has gone ---------- */
/* Same block on the standalone /thanks/ page and in place of the form. */
.thanks-page { display: grid; place-items: center; min-height: 100vh; padding: 40px 26px; }
.thanks { max-width: 520px; }
.thanks .eyebrow, .sent .eyebrow {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--faint); margin: 0 0 18px;
}
.thanks h1, .sent h2 {
  font-family: var(--serif); font-weight: 400; font-size: clamp(30px, 5vw, 42px);
  line-height: 1.15; color: var(--ink); margin: 0 0 14px;
}
.thanks .body, .sent .body {
  font-size: 16.5px; line-height: 1.7; color: var(--muted); margin: 0 0 28px;
}
.thanks .back {
  display: inline-block; text-decoration: none;
  border: 1px solid var(--accent); color: var(--accent);
  padding: 14px 30px; font-family: var(--mono); font-size: 12.5px;
  letter-spacing: .1em; text-transform: uppercase;
  transition: background .18s ease, color .18s ease;
}
.thanks .back:hover { background: var(--accent); color: var(--bg); }

/* The inline version keeps the form's footprint so the page does not jump. */
.sent {
  margin-top: 34px; max-width: 560px;
  border-left: 2px solid var(--accent); padding: 4px 0 4px 22px;
}
/* Smaller than the standalone page: this sits beside the CTA headline
   and must not compete with it. */
.sent h2 { font-size: 27px; margin-bottom: 10px; }
.sent .body { margin-bottom: 0; }

/* ---------- footer ---------- */
.foot {
  border-top: 1px solid var(--rule); padding: 26px 0 40px 0;
  display: flex; justify-content: space-between; gap: 18px; flex-wrap: wrap;
  font-family: var(--mono); font-size: 12px; color: var(--faint);
}


/* ==========================================================================
   Phones. The desktop layout puts three columns of context before the work,
   which reads fine side by side and badly when it stacks: on a 375px screen
   that was 2.5 screens of text before the first frame of video. Here the
   reel moves directly under the headline, and the writing follows it.
   ========================================================================== */
@media (max-width: 760px) {
  /* the bar was eating 119px of an 812px screen */
  .nav { padding-top: 14px; padding-bottom: 14px; gap: 10px; }
  .nav .name { font-size: 19px; }
  .nav ul { gap: 22px; }

  .hero { padding-top: 34px; }
  .hero h1 { font-size: clamp(34px, 10vw, 44px); max-width: 11ch; }
  .portrait { --portrait-size: 96px; }

  .reel { padding-top: 30px; }
  .about { margin-top: 46px; }
  .hero-cols { gap: 32px; }
  .bio p { font-size: 16px; }

  /* right-aligned values wrapped into a cramped column at this width */
  .fact { display: block; padding: 12px 0; }
  .fact dd { text-align: left; margin-top: 4px; }
  /* the <br>s stay: the source has no space around them, and the breaks are
     meaningful anyway (INA / BCIT are two separate schools). */

  /* the facts table and the client list are hidden on phones: stacked, they
     put another screen of small print between the bio and the work. Both are
     still in the HTML, so nothing is lost to search engines. */
  .side { display: none; }

  .sechead { margin-top: 62px; }
  .sechead .count { margin-left: 0; flex-basis: 100%; }
}

/* ---------- before / after ---------- */
/* Shown two ways on purpose. The default is a plain side-by-side pair, which
   needs no scripting and reads perfectly well. app.js adds .live and the same
   markup becomes a wipe. Before is on the left in both, so the reading order
   never changes under the reader's feet. */
.focus { margin-top: clamp(70px, 9vw, 116px); }
.focus-intro {
  color: var(--muted); font-size: 16px; line-height: 1.7;
  /* full content width, matching the frames below it */
  margin: 22px 0 0 0;
}
.cmp { margin: 34px 0 0 0; }
.cmp-frames { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.cmp-a, .cmp-b { position: relative; margin: 0; }
.cmp-frames img { width: 100%; height: auto; display: block; }
.cmp-tag {
  position: absolute; top: 10px; left: 10px;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink);
  background: rgba(12, 11, 10, .68); padding: 5px 9px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.cmp-b .cmp-tag { left: auto; right: 10px; }
.cmp-line, .cmp-range { display: none; }
.cmp figcaption {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .04em;
  color: var(--faint); line-height: 1.6; margin-top: 12px;
}

/* Upgraded: one frame, wiped between. */
.cmp.live .cmp-frames {
  display: block; position: relative; aspect-ratio: 16 / 9;
  background: #000; overflow: hidden; gap: 0;
  /* let a vertical swipe scroll the page; only sideways drags move the wipe */
  touch-action: pan-y;
}
.cmp.live .cmp-a, .cmp.live .cmp-b { position: absolute; inset: 0; }
.cmp.live .cmp-frames img { width: 100%; height: 100%; object-fit: cover; }
/* clip-path rather than a width on a wrapper: the image keeps its full size,
   so it never squashes as the handle moves */
.cmp.live .cmp-b { clip-path: inset(0 0 0 var(--cmp, 50%)); }
.cmp.live .cmp-line {
  display: block; position: absolute; top: 0; bottom: 0;
  left: var(--cmp, 50%); width: 1px; margin-left: -.5px;
  background: var(--ink); pointer-events: none;
}
.cmp.live .cmp-line::after {
  content: ""; position: absolute; top: 50%; left: 50%;
  width: 34px; height: 34px; transform: translate(-50%, -50%);
  border: 1px solid var(--ink); border-radius: 50%;
  background: rgba(12, 11, 10, .55);
  -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
/* The real control, invisible over the frame. Native range means drag, touch
   and arrow keys all work without reimplementing any of them. */
.cmp.live .cmp-range {
  display: block; position: absolute; inset: 0;
  width: 100%; height: 100%; margin: 0; padding: 0;
  opacity: 0; cursor: ew-resize; background: transparent;
  -webkit-appearance: none; appearance: none;
}
.cmp.live .cmp-range::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 44px; height: 100%;
}
.cmp.live .cmp-range::-moz-range-thumb { width: 44px; height: 100%; border: 0; border-radius: 0; }
.cmp.live .cmp-range:focus-visible ~ .cmp-line { outline: 2px solid var(--accent); }
@media (max-width: 620px) {
  .cmp-frames { grid-template-columns: 1fr; }
}

/* The form earns a second column beside the closing line: it is the last
   thing on the page, and stacked underneath it pushed the send button a
   long way from the sentence that asks for it. Only when there IS a form,
   so /portfolio's single button is not left stranded out to the side. */
@media (min-width: 940px) {
  .cta.split {
    display: grid; grid-template-columns: 1.05fr 1fr;
    gap: clamp(44px, 6vw, 86px); align-items: start;
  }
  .cta.split .cta-copy { min-width: 0; }
  .cta.split .big { font-size: clamp(26px, 3.2vw, 40px); max-width: 20ch; }
  .cta.split .form, .cta.split .sent { margin-top: 6px; max-width: none; }
}

/* ---------- burger, phones only ---------- */
/* Five labels on one row was always tight; below 620px the nav used to wrap
   to two rows and grow the sticky bar. A burger keeps the bar one row tall
   and gives every link a proper hit target. */
.burger { display: none; }

@media (max-width: 620px) {
  /* .nav keeps its wrap: the name and burger share row one, and the open
     panel is width:100% so it lands on row two instead of squeezing them. */
  .burger {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 44px; height: 44px; margin-right: -10px;   /* optical, not visual, edge */
    padding: 0; background: none; border: 0; cursor: pointer; color: var(--ink);
  }
  .burger span {
    display: block; width: 22px; height: 1.5px; margin: 0 auto;
    background: currentColor;
    transition: transform .22s ease, opacity .16s ease;
  }
  .burger:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
  .burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
  .burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

  .nav ul {
    display: none; width: 100%; flex-direction: column; gap: 0;
    margin-top: 14px; border-top: 1px solid var(--rule);
  }
  .nav.open ul { display: flex; }
  .nav ul li { border-bottom: 1px solid var(--hair); }
  .nav ul li a { display: block; padding: 15px 2px; font-size: 13px; }
  .nav ul li:last-child a { color: var(--accent); }
}
