/* jonasstevens.eu — shared stylesheet
   Ported directly from "Jonas Stevens Portfolio.dc.html" (Claude Design canvas
   mockup): small-caps typography throughout in the accent terracotta, a
   colour band keyed to the wordmark's rendered width, a rotated edge label,
   and captions that sit outside the image rather than over it.
*/

:root {
  --accent: #A8422A;
  --accent-dark: #7E2F1C;
  --subtitle-ink: #9C4630;
  --ink: #1a1a1a;
  --gray: #6f6f6f;
  --gray-dark: #4a4a4a;
  --paper: #ffffff;
  --band: #A7CBD6;
  --band-w: 480px;
  --band-l: 40px;
  --header-h: 118px;
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  position: relative;
  display: flex;
  flex-direction: column;
  overflow-x: clip;
}

a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-dark); }
::selection { background: #F5D9D1; }
img { max-width: 100%; display: block; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}

/* ---------- band + edge label (fixed, full page) ---------- */
.band-layer {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--band-css, linear-gradient(to right, transparent var(--band-l), var(--band) var(--band-l), var(--band) calc(var(--band-l) + var(--band-w)), transparent calc(var(--band-l) + var(--band-w))));
}
/* projects overview (merged studium+beruf page): whichever orientation was
   picked for this visit — vertical stripe off the right (old "beruf" look)
   or a horizontal strip near the bottom (old "studium" look). */
body.band-beruf .band-layer {
  --band-css: linear-gradient(to right, transparent calc(74vw - var(--band-w)), var(--band) calc(74vw - var(--band-w)), var(--band) 74vw, transparent 74vw);
}
body.band-studium .band-layer {
  --band-css: linear-gradient(to bottom, transparent calc(100% - (var(--band-l) + var(--band-w))), var(--band) calc(100% - (var(--band-l) + var(--band-w))), var(--band) calc(100% - var(--band-l)), transparent calc(100% - var(--band-l)));
}

.edge-label {
  position: fixed;
  right: 6px;
  top: 0; bottom: 0;
  width: 0;
  z-index: 6;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.edge-label span {
  writing-mode: vertical-rl;
  transform: rotate(180deg) translateY(-0.12em);
  font-variant: small-caps;
  font-size: 26px;
  letter-spacing: .06em;
  color: var(--accent);
  white-space: nowrap;
  margin-right: -0.30em;
}
@media (min-width: 900px) { .edge-label span { font-size: 32px; } }
@media (min-width: 1300px) { .edge-label span { font-size: 38px; } }

/* ---------- header ---------- */
header.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 5;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 32px 5vw 0 5vw;
}
@media (min-width: 700px) { header.site-header { padding-top: 52px; } }

.header-fade {
  position: absolute;
  left: 0; right: 0; top: 0;
  height: calc(100% + 72px);
  pointer-events: none;
  z-index: -1;
  transition: height .25s ease;
}
.header-fade.menu-open { height: calc(100% + 150px); }
.header-fade::before,
.header-fade::after {
  content: "";
  position: absolute;
  inset: 0;
}
.header-fade::before {
  background: linear-gradient(to bottom, #fff 0%, #fff 58%, rgba(255,255,255,.86) 78%, rgba(255,255,255,0) 100%);
  -webkit-mask-image: var(--white-mask, none);
  mask-image: var(--white-mask, none);
}
.header-fade::after {
  /* paints the band's OWN colour into the header, in the exact slice
     --band-mask leaves unmasked by ::before's white layer. This has to be
     an opaque fill of --band itself, not a "hole" that just exposes
     whatever main content happens to have scrolled up underneath the fixed
     header — on pages with a lot of scrolling image content (the projects
     overview) a plain transparent gap let arbitrary photos show through
     behind the nav instead of a clean band colour.
     Same vertical fade stops as ::before's white gradient (0%/58%/78%/100%),
     just in --band instead of white, so the band fades out softly into the
     page instead of ending in a hard rectangular edge. */
  background: linear-gradient(to bottom,
    var(--band) 0%,
    var(--band) 58%,
    color-mix(in srgb, var(--band) 86%, transparent) 78%,
    transparent 100%);
  -webkit-mask-image: var(--band-mask, none);
  mask-image: var(--band-mask, none);
}
/* fade-plain pages (horizontal-orientation overview) don't want any band
   bleeding into the header at all — --band-mask is left unset there, which
   without this would default to "unmasked" (i.e. fully visible) rather
   than hidden. */
body.fade-plain .header-fade::after { display: none; }
/* vertical-band pages (about / project / portfolio / kontakt): gap over the band */
body.fade-vstripe .header-fade {
  --white-mask: linear-gradient(to right, #000 0, #000 var(--band-l), transparent var(--band-l), transparent calc(var(--band-l) + var(--band-w)), #000 calc(var(--band-l) + var(--band-w)), #000 100%);
  --band-mask: linear-gradient(to right, transparent 0, transparent var(--band-l), #000 var(--band-l), #000 calc(var(--band-l) + var(--band-w)), transparent calc(var(--band-l) + var(--band-w)), transparent 100%);
}
/* beruf overview: same idea, band sits at 74vw */
body.fade-beruf .header-fade {
  --white-mask: linear-gradient(to right, #000 0, #000 calc(74vw - var(--band-w)), transparent calc(74vw - var(--band-w)), transparent 74vw, #000 74vw, #000 100%);
  --band-mask: linear-gradient(to right, transparent 0, transparent calc(74vw - var(--band-w)), #000 calc(74vw - var(--band-w)), #000 74vw, transparent 74vw, transparent 100%);
}
/* horizontal-orientation overview: band is a strip near the bottom, no header gap needed */
body.fade-plain .header-fade { --white-mask: none; --band-mask: none; }
/* portfolio: hard edge, no fade — the header sits on a solid white bar.
   No colour band either: a stripe cutting across the PDF viewer just
   looked like a rendering glitch, so the portfolio page goes bandless. */
body.fade-none .header-fade { display: none; }
body.fade-none header.site-header { background: #fff; }
body.fade-none .band-layer { display: none; }
/* home: hero fits in one viewport, nothing scrolls underneath the fixed
   header there, so it doesn't need the band-through-header treatment —
   plain header, no gradient/band colour (this is how it looked before). */
body.is-home .header-fade { display: none; }

.header-inner-spacer { flex: none; }

.wordmark-block {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: max-content;
  gap: 2px;
  cursor: pointer;
  position: relative;
  z-index: 2;
}
.wordmark-block .name {
  font-variant: small-caps;
  font-size: clamp(26px, 3.4vw, 52px);
  line-height: 1;
  letter-spacing: .02em;
  color: var(--accent);
  white-space: nowrap;
}
.wordmark-block .subtitle {
  font-variant: small-caps;
  font-size: clamp(14px, 1.78vw, 27px);
  line-height: 1.2;
  color: var(--subtitle-ink);
  text-align: justify;
  text-align-last: justify;
}

nav.main-nav {
  position: relative;
  z-index: 2;
  display: flex;
  align-items: center;
  height: clamp(26px, 3.4vw, 52px);
  gap: clamp(14px, 2.6vw, 38px);
  font-variant: small-caps;
  font-size: clamp(14px, 1.6vw, 32px);
  letter-spacing: .04em;
  color: var(--accent);
  white-space: nowrap;
}
nav.main-nav .nav-links {
  display: flex;
  align-items: center;
  gap: clamp(14px, 2.6vw, 38px);
}
nav.main-nav a:hover { text-decoration: underline; }

.projects-menu { position: relative; display: flex; flex-direction: column; align-items: center; }
.projects-menu > a { cursor: pointer; }
.projects-dropdown {
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%);
  padding-top: 10px;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  font-size: clamp(13px, 1.3vw, 26px);
}
.projects-menu.open .projects-dropdown { display: flex; }

.lang-switch { font-variant: small-caps; letter-spacing: .04em; cursor: pointer; }

.menu-toggle {
  display: none;
  width: 30px; height: 30px;
  border: none; background: none;
  cursor: pointer;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  position: relative; z-index: 2;
}
.menu-toggle span { display: block; height: 1.5px; background: var(--accent); }

.mobile-nav {
  display: none;
  position: fixed;
  inset: 0;
  background: #fff;
  z-index: 20;
  padding: 100px 30px 30px;
  overflow-y: auto;
}
.mobile-nav.open { display: block; }
.mobile-nav a, .mobile-nav .sub-label {
  display: block;
  padding: 12px 0;
  font-variant: small-caps;
  font-size: 22px;
  color: var(--accent);
  border-bottom: 1px solid rgba(168,66,42,.15);
}
.mobile-nav .sub-label { color: #b98470; font-size: 14px; border-bottom: none; padding-bottom: 2px; }

/* ---------- main content ---------- */
main { position: relative; z-index: 1; flex: 1; min-height: 0; display: flex; flex-direction: column; }

footer.site-footer {
  position: relative; z-index: 1;
  padding: 20px 5vw 26px;
  font-size: 12px;
  color: var(--gray);
  display: flex;
  justify-content: space-between;
  gap: 20px;
  flex-wrap: wrap;
}
footer.site-footer a:hover { color: var(--accent-dark); }

/* ---------- home ---------- */
.home-hero {
  position: relative;
  z-index: 4;
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: flex-end;
  padding: 48px 5vw 76px;
}
.dotbg {
  position: fixed;
  left: 0;
  top: var(--header-h);
  height: calc(100vh - var(--header-h) + 6vh);
  aspect-ratio: 754 / 561;
  transform: translateX(-18.2%);
  z-index: 0;
  pointer-events: none;
  opacity: 0.5;
  mix-blend-mode: multiply;
  background: url("../img/home/dot-bg.png") center / contain no-repeat;
}

.tile-grid {
  position: relative;
  display: grid;
  /* Pure proportional layout, no fixed px caps anywhere: 3 square columns +
     1 portfolio column, sized as fr tracks in a 1.41421:1 ratio (sqrt(2):1).
     Because fr tracks always consume exactly the container's full width
     (minus gaps) with no leftover and no possibility of overflow, this
     grid — combined with aspect-ratio on the tiles themselves, below —
     guarantees at every viewport width, with no JS involved: the 3 square
     tiles are true squares, the portfolio tile is true A4 ratio, the row
     spans edge-to-edge (so tile 1's left edge = the wordmark's left edge,
     and the portfolio tile's right edge = the nav's right edge, both via
     the same shared 5vw padding), and every gap is identical. */
  grid-template-columns: repeat(3, 1.41421fr) 1fr;
  gap: clamp(16px, 2.2vw, 40px);
  width: 100%;
  align-items: end;
}
.tile-wrap { position: relative; cursor: pointer; display: block; }
.tile {
  width: 100%;
  aspect-ratio: 1 / 1;
  background: #f2f2f2;
  display: block;
  overflow: hidden;
}
/* ISO 216 A4 portrait ratio (1 : sqrt(2)), derived purely from the column's
   own resolved width via aspect-ratio — no JS measurement needed, and no
   way for it to drift off-ratio the way a JS-measured height could. */
.tile-wrap.portfolio-tile .tile {
  aspect-ratio: 1 / 1.41421;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0,0,0,.13);
}
.tile img {
  width: 100%; height: 100%; object-fit: cover;
  transform: scale(1.06);
  transition: transform .5s cubic-bezier(.25,.8,.25,1);
}
.tile-wrap:hover .tile img { transform: scale(1.14); }
.tile-wrap.portfolio-tile .tile img { object-fit: contain; transform: scale(1); }
.tile-wrap.portfolio-tile:hover .tile img { transform: scale(1.05); }
.tile-label-v {
  position: absolute;
  right: -0.62em;
  bottom: 14px;
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-variant: small-caps;
  letter-spacing: .03em;
  line-height: 1;
  color: var(--accent);
  pointer-events: none;
  white-space: nowrap;
  font-size: clamp(15px, 1.6vw, 28px);
}
.tile-label-v.has-h { bottom: 0.30em; }
.tile-label-h {
  position: absolute;
  right: 0.30em;
  bottom: -0.62em;
  font-variant: small-caps;
  letter-spacing: .03em;
  line-height: 1;
  color: var(--accent);
  pointer-events: none;
  white-space: nowrap;
  font-size: clamp(15px, 1.6vw, 28px);
}

@media (max-width: 760px) {
  /* 2x2: both columns the same width (so the two square tiles that land
     side by side match each other), each tile keeping its own aspect-ratio
     — square tiles stay square, the portfolio tile stays A4, and column 1's
     left edge / column 2's right edge still meet the container's edges. */
  .tile-grid { grid-template-columns: repeat(2, 1fr); }
  /* The portfolio tile shares its column with a square tile (above it) —
     filling the column's full width like it does in the single-row desktop
     layout would make it taller than that square (A4 is taller than a
     square of the same width), breaking the "every tile is the same
     height" rule. Instead size it by HEIGHT: width = column-width / sqrt(2)
     keeps its rendered height equal to the square tiles' height (which
     equals the shared column width), and margin-left:auto keeps it flush
     against the column's right edge — the real leftover space this leaves
     on its left is why the gap to its left-hand neighbour reads bigger
     than the gap in the row above; that's expected, not a bug. */
  .tile-wrap.portfolio-tile .tile {
    width: calc(100% / 1.41421);
    margin-left: auto;
  }
}
@media (max-width: 480px) {
  /* 1x4 stacked: each tile is full width, still true to its own ratio.
     Reset the 760px breakpoint's portfolio-tile narrowing — there's no
     square sharing its row here (each tile is alone on its own row), so
     it should go back to filling its column like every other tile. */
  .tile-grid { grid-template-columns: 1fr; }
  .tile-wrap.portfolio-tile .tile { width: 100%; margin-left: 0; }
}

/* ---------- projects overview (merged studium+beruf page) ---------- */
/* Each <section class="ov-section"> is the sticky containing block for its
   own .ov-edge-sticky label. Padding/margin placement here is deliberate:
   .ov-section carries the top padding (so the label's static position and
   the grid's first row line up exactly) but NEVER a bottom padding of its
   own — that way a section's box ends exactly at the bottom of its last
   tile row, so native position:sticky naturally releases the label right
   as that row's bottom reaches the sticky offset, and it scrolls away
   with it. The gap before the next section is pure margin on that next
   section, which sits outside the previous section's box and therefore
   never shifts its release point. The last section gets its own trailing
   padding for footer breathing room — since it's last, that only makes
   its label stay stuck a little longer, which is the wanted behaviour. */
.ov-section {
  position: relative;
  z-index: 4;
  padding-top: 60px;
  /* the header is fixed and not part of normal flow, so #beruf/#studium
     anchor links (and any browser "scroll to fragment" on load) need this
     to know to stop short of the section's own top instead of sliding it
     out from under the header. */
  scroll-margin-top: var(--header-h, 132px);
}
.ov-section + .ov-section { margin-top: 90px; }
.ov-section:last-child { padding-bottom: 90px; }

.overview-grid {
  position: relative;
  z-index: 4;
  display: grid;
  grid-template-columns: repeat(4, minmax(190px, 300px));
  gap: 62px 40px;
  padding: 0 5vw;
}
@media (max-width: 1180px) { .overview-grid { grid-template-columns: repeat(3, minmax(190px, 300px)); } }
@media (max-width: 900px)  { .overview-grid { grid-template-columns: repeat(2, minmax(190px, 300px)); } }
@media (max-width: 520px)  { .overview-grid { grid-template-columns: 1fr; } }

/* sticky label that follows its section (Beruf / Studium) up to a fixed
   offset under the header, then hands off to the next section's label as
   you scroll past it. Uses a flex wrapper (not a bare absolutely-positioned
   span) so it actually gets a real box in a zero-height sticky parent. */
.ov-edge-sticky {
  position: sticky;
  top: 168px;
  height: 0;
  z-index: 6;
  pointer-events: none;
  display: flex;
  justify-content: flex-end;
  align-items: flex-start;
}
.ov-edge-sticky span {
  writing-mode: vertical-rl;
  transform: rotate(180deg) translateY(-0.12em);
  font-variant: small-caps;
  font-size: 26px;
  letter-spacing: .06em;
  color: var(--accent);
  white-space: nowrap;
  margin-right: -0.30em;
}
@media (min-width: 900px) { .ov-edge-sticky span { font-size: 32px; } }
@media (min-width: 1300px) { .ov-edge-sticky span { font-size: 34px; } }

/* ---------- about ---------- */
.about-wrap {
  position: relative; z-index: 4;
  display: flex;
  flex-direction: column;
  padding: 78px 5vw 6vh;
}
.about-top {
  display: grid;
  grid-template-columns: calc(var(--band-w, 340px) - 30px) minmax(0, 1fr);
  gap: 0 30px;
  align-items: start;
}
.about-portrait { position: relative; width: 100%; max-width: 100%; aspect-ratio: 3 / 4; background: #f2f2f2; }
.about-portrait img { width: 100%; height: 100%; object-fit: cover; }
.about-text { display: flex; flex-direction: column; gap: 22px; max-width: 74ch; text-align: left; }
.about-text .greeting { font-size: 22px; font-weight: 600; text-align: left; }
.about-text p { margin: 0; font-size: 17px; line-height: 1.6; text-align: left; }

.cv-grid {
  display: grid;
  grid-template-columns: calc(var(--band-w, 340px) - 30px) minmax(0, 1fr);
  gap: 20px 30px;
  font-size: 17px;
  line-height: 1.45;
  padding-top: 64px;
}
.cv-grid h2 { grid-column: 2; font-size: 20px; font-weight: 600; margin: 0; }
.cv-grid .spacer { height: 22px; grid-column: 1 / -1; }
.cv-row-when { text-align: right; white-space: nowrap; color: var(--ink); }
.cv-row-what > div:first-child { color: var(--ink); }
.cv-row-what .role { color: var(--gray-dark); }
.cv-grid .skills-line { grid-column: 2; }
.skills-list { grid-column: 2; display: flex; flex-direction: column; gap: 14px; }
.skills-group { display: flex; flex-direction: column; gap: 4px; }
.skills-list .skill-row { color: var(--ink); }
.skills-list .skills-note { color: var(--gray-dark); font-size: 15px; margin-top: 2px; }

@media (max-width: 780px) {
  .about-top { grid-template-columns: 1fr; }
  .about-portrait { max-width: 300px; }
  .cv-grid { grid-template-columns: 1fr; }
  .cv-row-when { text-align: left; }
  .cv-grid h2, .cv-grid .skills-line, .skills-list { grid-column: 1; }
}

/* ---------- project detail ---------- */
.project-wrap {
  position: relative; z-index: 4;
  flex: 1; min-height: 0;
  display: flex;
  gap: 5vw;
  align-items: flex-start;
  padding: 60px 5vw 6vh;
}
.slide-col { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.slideshow {
  position: relative;
  height: 58vh;
  min-height: 320px;
  max-height: 620px;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.slideshow .slides {
  position: relative;
  width: 100%; height: 100%;
  display: flex;
  transition: transform .5s cubic-bezier(.4,0,.2,1);
}
.slideshow .slide {
  flex: 0 0 100%;
  height: 100%;
  display: flex; align-items: center; justify-content: center;
}
/* every slide is exactly as tall as the frame; width follows the image's
   own aspect ratio, so portrait and landscape shots sit side by side at
   the same height instead of being forced into one uniform box. */
.slideshow .slide img { height: 100%; width: auto; max-width: 100%; object-fit: contain; }
.slide-nav {
  position: absolute; top: 50%; transform: translateY(-50%);
  font-size: 44px; font-weight: 200; color: #8a8a8a;
  background: none; border: none; cursor: pointer; line-height: 1;
  padding: 8px;
}
@media (min-width: 700px) { .slide-nav { font-size: 56px; } }
.slide-nav.prev { left: 8px; }
.slide-nav.next { right: 8px; }
.slide-nav:hover { color: var(--accent); }

/* Width is set by site.js's alignProjectText() to run exactly from the
   "Über mich"/"About Me" nav link's left edge to the En/De button's right
   edge — both flex-layout positions the CSS side alone can't predict (nav
   link position depends on the rendered nav content's own width). This
   flex-basis is just the no-JS / pre-measurement fallback, roughly the
   same share of the row the fixed nav-aligned width usually works out to.
   .slide-col is flex:1, so whatever width this box doesn't use goes
   straight to the slideshow instead of sitting empty. */
.project-text { display: flex; flex-direction: column; gap: 16px; flex: 0 0 auto; width: 38%; }
.project-text .title-line { font-size: 20px; line-height: 1.3; }
.project-text .title-line strong { font-weight: 700; }
.project-text .meta { font-size: 17px; color: var(--gray); }
.project-text .body { display: flex; flex-direction: column; gap: 14px; font-size: 16px; line-height: 1.55; text-align: justify; }
.project-text .body p { margin: 0; }
.dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
  padding-top: 18px;
}
.dots .dot { width: 7px; height: 7px; border-radius: 50%; background: #d6d6d6; border: none; padding: 0; cursor: pointer; }
.dots .dot.active { background: var(--accent); }
.back-link { font-variant: small-caps; font-size: 15px; letter-spacing: .04em; color: var(--accent); margin-bottom: 4px; }
.back-link:hover { text-decoration: underline; }

@media (max-width: 780px) {
  .project-wrap { flex-direction: column; }
  .slideshow { height: 50vh; }
  .project-text { padding-top: 24px; flex-basis: auto; width: auto !important; }
}

/* ---------- kontakt ---------- */
.kontakt-wrap {
  position: relative; z-index: 4;
  display: grid;
  grid-template-columns: minmax(0, .62fr) minmax(0, 1fr);
  gap: 5vw;
  align-items: start;
  padding: 64px 5vw 8vh;
  min-height: calc(100vh - 132px);
}
.kontakt-left { display: flex; flex-direction: column; gap: 10px; font-size: 17px; line-height: 1.6; padding-top: 6vh; }
.kontakt-left h1 { font-variant: small-caps; font-size: 34px; color: var(--accent); line-height: 1; margin: 0; font-weight: 400; }
.kontakt-left .loc { color: var(--gray); }
.kontakt-right { display: flex; flex-direction: column; gap: 18px; max-width: 52ch; padding-top: 6vh; }
.kontakt-right p { margin: 0; font-size: 16px; line-height: 1.6; color: var(--ink); }
.btn-outline {
  align-self: flex-start;
  border: 1px solid var(--accent);
  background: transparent;
  color: var(--accent);
  padding: 11px 26px;
  font-variant: small-caps;
  font-size: 21px;
  letter-spacing: .04em;
  cursor: pointer;
}
.btn-outline:hover { background: var(--accent); color: #fff; }

@media (max-width: 700px) { .kontakt-wrap { grid-template-columns: 1fr; gap: 30px; } }

/* ---------- portfolio ---------- */
.portfolio-wrap {
  position: relative; z-index: 4;
  flex: 1; min-height: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 28px 5vw 4vh;
}
.portfolio-frame {
  position: relative;
  flex: 1;
  min-height: 62vh;
  max-height: 80vh;
  overflow-y: auto;
  overflow-x: hidden;
  background: #f2f2f2;
  border: 1px solid #e6e6e6;
  -webkit-overflow-scrolling: touch;
}
.portfolio-frame img {
  display: block;
  width: 100%;
  height: auto;
  border-bottom: 1px solid #e6e6e6;
}
.portfolio-frame img:last-child { border-bottom: 0; }
.portfolio-actions {
  display: flex; justify-content: flex-end; gap: 24px;
}
.btn-pf {
  font-variant: small-caps;
  font-size: 15px;
  letter-spacing: .04em;
}
@media (min-width: 700px) { .btn-pf { font-size: 19px; } }
.btn-pf.view { color: var(--accent); }
.btn-pf.view:hover { text-decoration: underline; color: var(--accent-dark); }
.btn-pf.dl { color: var(--gray-dark); }
.btn-pf.dl:hover { text-decoration: underline; color: var(--accent-dark); }

/* chrome-less pdf-only page */
body.pdf-only { margin: 0; height: 100vh; display: block; }
body.pdf-only iframe { width: 100vw; height: 100vh; border: none; display: block; }

@media (max-width: 700px) {
  nav.main-nav { display: none; }
  .menu-toggle { display: flex; }
}
