/* ==========================================================================
   Mike Remshard — shared site styles
   Layout shell (sidebar / mobile bar / content wrap), grain, scroll reveal.
   Page-specific styling stays in each page's Tailwind classes.
   ========================================================================== */

@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-display: swap; }
@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-Italic.ttf') format('truetype'); font-weight: 400; font-style: italic; font-display: swap; }
@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-Bold.ttf') format('truetype'); font-weight: 700; font-style: normal; font-display: swap; }
@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-BoldItalic.ttf') format('truetype'); font-weight: 700; font-style: italic; font-display: swap; }
@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-Black.ttf') format('truetype'); font-weight: 900; font-style: normal; font-display: swap; }
@font-face { font-family: 'LT Sip Text'; src: url('../fonts/LTSipText-BlackItalic.ttf') format('truetype'); font-weight: 900; font-style: italic; font-display: swap; }

:root {
  --onyx: #0f120f;
  --porcelain: #fafaf5;
  --jasmine: #f5d970;
  --ash: #b7b8b7;

  /* Desktop shell — values from Figma (1440 frame) */
  --edge: 30px;                 /* sidebar inset from top/left/bottom */
  --sidebar-w: 229px;
  --sidebar-radius: 10px;
  --content-gap: 91px;          /* sidebar right edge -> content left edge */
  --content-left: calc(var(--edge) + var(--sidebar-w) + var(--content-gap)); /* 350px */
  --content-max: 1000px;
  --content-min: 600px;
  --content-right: 48px;        /* min breathing room on the right below 1440 */

  /* Mobile shell — values from Figma (390 frame) */
  --m-edge: 24px;
  --m-bar-h: 87px;
  /* Notch / home-indicator insets (pages use viewport-fit=cover). Zero in a normal browser tab. */
  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
  --m-body-lh: 23.5px;          /* body copy line-height on phones (18px Mr Eaves, Figma 390 frames) */

  /* Motion */
  --nav-hover-dur: 200ms;        /* every hover colour change fades at this speed */
  --reveal-dur: 900ms;
  --reveal-shift: 24px;         /* fade-up distance */

  /* Grain */
  --grain-opacity: 0.32;
  --grain-blend: overlay;       /* overlay + mid-grey noise = texture without shifting the page's average colour */
  --grain-size: 220px;
}

/* Body text is Mr Eaves Modern Book (Adobe Fonts weight 300; the kit also has Book Italic and Bold). */
/* Always reserve the scrollbar's space, so nothing shifts sideways when the open menu locks
   scrolling or when one page scrolls and the next does not (browsers with classic scrollbars). */
html { scrollbar-gutter: stable; }
body { font-family: 'mr-eaves-modern', sans-serif; font-weight: 300; }
/* Mobile-only / desktop-only line breaks: <br class="m-br"> and <br class="d-br"> */
.d-br { display: none; }
@media (min-width: 1024px) {
  .m-br { display: none; }
  .d-br { display: inline; }
}
/* Tailwind's reset makes <b>/<strong> "bolder", which is relative: from 300 that is only
   400. Pin bold to the kit's Bold (700) so emphasis stays bold. */
b, strong { font-weight: 700; }

/* ---------- Content wrap: left-anchored, max-width, extra space goes right ---------- */
.wrap {
  padding-left: max(var(--m-edge), var(--safe-left));
  padding-right: max(var(--m-edge), var(--safe-right));
}
@media (min-width: 1024px) {
  :root { --m-body-lh: 22px; }  /* desktop rules that inherit the mobile value keep their old spacing */
  .wrap {
    padding: 0;
    margin-left: var(--content-left);
    margin-right: var(--content-right);
    max-width: var(--content-max);
    min-width: var(--content-min);
  }
}

.site-main {
  padding-top: calc(var(--m-edge) + var(--m-bar-h) + 32px);
  padding-bottom: 64px;
  overflow-x: clip;   /* full-bleed bands use 100vw; never let them cause sideways scroll */
}
@media (min-width: 1024px) {
  .site-main { padding-top: var(--edge); }
}

/* ---------- Desktop sidebar: fixed, full-height, floating ---------- */
.sidebar {
  display: none;
}
@media (min-width: 1024px) {
  .sidebar {
    position: fixed;
    z-index: 40;
    top: var(--edge);
    bottom: var(--edge);
    left: var(--edge);
    width: var(--sidebar-w);
    border-radius: var(--sidebar-radius);
    background: var(--onyx);
    color: var(--porcelain);
    padding: 50px 30px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;  /* 75px gaps at a 900px-tall window, as in Figma */
    gap: 24px;                        /* floor on short windows; then it scrolls */
    overflow-y: auto;
    scrollbar-width: none;
  }
  .sidebar::-webkit-scrollbar { display: none; }
}
/* Short laptop windows (e.g. 1366x768 minus browser chrome): tighten so the
   contact block stays visible. Below ~650px tall the sidebar scrolls. */
@media (min-width: 1024px) and (max-height: 820px) {
  .sidebar { padding-top: 36px; padding-bottom: 36px; gap: 20px; }
  .sidebar .nav-list { gap: 18px; }
  .sidebar .contact { font-size: 16px; line-height: 20px; }
}

.sidebar__logo { display: block; }
.sidebar__logo .mark { display: block; width: 64px; height: 58px; margin: 0 auto; fill: var(--porcelain); }
.sidebar__logo .title { display: block; width: 169px; height: auto; margin-top: 9px; }
.sidebar__logo .subtitle { display: block; width: 168px; height: auto; margin-top: 12px; margin-left: 1px; }

.nav-list {
  display: flex;
  flex-direction: column;
  gap: 26.5px;                 /* 43.5px pitch, as in Figma */
  font-family: 'LT Sip Text', Georgia, serif;
  font-size: 18px;
  line-height: 17px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.nav-list a { color: var(--porcelain); transition: color var(--nav-hover-dur) ease; }
.nav-list a[aria-current="page"] { color: var(--jasmine); }
@media (hover: hover) {
  .nav-list a:hover { color: var(--jasmine); }
}

.contact { font-size: 18px; line-height: 22px; }
.sidebar .contact { width: 176px; }  /* Figma lets the contact block run 7px into the right padding */
.contact__note { color: var(--ash); }
.contact__details { margin-top: 15px; color: var(--porcelain); }
.contact__details a { color: inherit; font-weight: 700; transition: color var(--nav-hover-dur) ease; }
@media (hover: hover) {
  .contact__details a:hover { color: var(--jasmine); }
}

/* ---------- Mobile bar + menu: floating card ---------- */
.mobile-bar {
  position: fixed;
  z-index: 50;
  top: calc(var(--m-edge) + var(--safe-top));
  left: max(var(--m-edge), var(--safe-left));
  right: max(var(--m-edge), var(--safe-right));
  border-radius: var(--sidebar-radius);
  background: var(--onyx);
  color: var(--porcelain);
}
@media (min-width: 1024px) {
  .mobile-bar, .menu-sheet { display: none; }
}
.mobile-bar__row {
  /* Own compositing layer, always: otherwise the browser re-draws the logo a fraction of a
     pixel differently whenever the menu behind it starts or stops fading. */
  will-change: transform;
  height: var(--m-bar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 16px 0 24px;
}
.mobile-logo { display: flex; align-items: center; gap: 12px; }
.mobile-logo .mark { width: 64px; height: 58px; fill: var(--porcelain); flex-shrink: 0; }
.mobile-logo .words { display: flex; flex-direction: column; gap: 12px; }
.mobile-logo .title { width: 170px; height: auto; }
.mobile-logo .subtitle { width: 169px; height: auto; margin-left: 1px; }
@media (max-width: 359px) {
  .mobile-logo .words { display: none; }
}

.menu-toggle {
  width: 44px; height: 44px;
  display: grid; place-content: center; gap: 7px;
  color: var(--porcelain);
}
.menu-toggle span {
  display: block; width: 31px; height: 1px; background: currentColor;
  transition: transform 250ms ease, opacity 200ms ease;
}
.mobile-bar.is-open .menu-toggle span:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.mobile-bar.is-open .menu-toggle span:nth-child(2) { opacity: 0; }
.mobile-bar.is-open .menu-toggle span:nth-child(3) { transform: translateY(-8px) rotate(-45deg); }

/* Open state (Figma MOBILE NAV EXPANDED, 390x844): a full-screen Onyx sheet fades in
   behind the bar, so the bar's logo row stays put and the hamburger turns into the close X.
   The sheet is its own element (not part of the bar) so a page transition can fade it
   separately: html.menu-open shows the sheet, .mobile-bar.is-open shows the menu on it. */
.menu-sheet {
  position: fixed;
  inset: 0;
  z-index: 45;
  background: var(--onyx);
  opacity: 0;
  visibility: hidden;
  touch-action: none;
  transition: opacity 300ms ease, visibility 0s linear 300ms;
}
html.menu-open .menu-sheet {
  opacity: 1;
  visibility: visible;
  transition: opacity 300ms ease, visibility 0s;
}
/* The menu never scrolls: it is exactly the visible screen (100dvh, so the browser's toolbars
   are accounted for) from the logo's bottom edge down. The link group sits centred between the
   logo and the contact block, which is pinned to the bottom. On a short screen the gaps between
   the links close up first (32px down to 10px), then the space above and below the group. */
.mobile-menu {
  --menu-top: calc(var(--m-edge) + var(--safe-top) + var(--m-bar-h) - 14px);   /* logo's bottom edge */
  position: fixed;
  top: var(--menu-top);
  left: 0; right: 0;
  height: calc(100dvh - var(--menu-top));
  overflow: hidden;
  touch-action: none;
  opacity: 0;
  visibility: hidden;
  transition: opacity 350ms ease, visibility 0s linear 350ms;
}
.mobile-bar.is-open .mobile-menu {
  opacity: 1;
  visibility: visible;
  transition: opacity 300ms ease 100ms, visibility 0s;
}
.mobile-menu > div { height: 100%; }
.mobile-menu__inner {
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: 0 max(var(--m-edge), var(--safe-right)) calc(53px + var(--safe-bottom)) max(var(--m-edge), var(--safe-left));
}
.mobile-menu__inner::before,
.mobile-menu__inner::after { content: ''; flex: 1 1 24px; min-height: 0; }   /* equal space above and below the links */
.mobile-menu__inner::after { order: 1; }
.mobile-menu .contact { order: 2; flex: none; font-size: 18px; line-height: 24px; }
.mobile-menu .contact__details { line-height: 23.5px; }
.mobile-menu .nav-list {
  /* 7 links of 19px: 32px apart at rest (325px), no closer than 10px (193px). The huge
     shrink factor makes this group give way before the spacers do. */
  flex: 0 1000 325px; min-height: 193px;
  justify-content: space-between; gap: 0;
  align-items: center; font-size: 22px; line-height: 19px;
}
@media (max-height: 600px) {
  .mobile-menu .contact__note { display: none; }   /* short screens (iPhone SE with toolbars showing): keep the phone and address */
}
html.menu-open { overflow: hidden; }

/* ---------- Copyright line (the full footer was dropped; not in Figma) ---------- */
.site-copyright {
  font-size: 14px;
  line-height: 1.4;
  opacity: 0.6;
  padding-bottom: 32px;
}

/* ---------- Page transitions ----------
   Three stages, as in the guidelines:
     1. exit   — the leaving page's content fades out
     2. blend  — the two page backgrounds cross-fade
     3. enter  — the arriving page's content fades in
   The navigation (desktop sidebar, mobile bar) never fades: it holds still through all three.
   Built on cross-document view transitions: naming <main> pulls the content out
   of the root snapshot, so "root" is the background (plus anything unnamed) and
   can be timed separately. Browsers without support just navigate normally. */
/* @view-transition must sit at the top level: nesting it inside @media makes
   Chromium drop the whole block. Reduced-motion users get the plain navigation
   because the stage animations below are what create the effect. */
@view-transition { navigation: auto; }

@media (prefers-reduced-motion: no-preference) {
  :root {
    --t-exit: 500ms;
    --t-blend: 900ms;
    --t-enter: 1200ms;
  }

  main { view-transition-name: content; }
  .sidebar { view-transition-name: nav; }
  .mobile-bar { view-transition-name: navbar; }
  html.menu-open .menu-sheet { view-transition-name: menu-sheet; }

  /* 1. content out */
  ::view-transition-old(content) {
    animation: vt-fade-out var(--t-exit) ease both;
  }
  /* 2. backgrounds cross-fade, once the content has cleared */
  ::view-transition-old(root) {
    animation: vt-fade-out var(--t-blend) ease-in-out var(--t-exit) both;
  }
  ::view-transition-new(root) {
    animation: vt-fade-in var(--t-blend) ease-in-out var(--t-exit) both;
  }
  /* 3. content in, after the new background is in place */
  ::view-transition-new(content) {
    animation: vt-fade-in var(--t-enter) ease calc(var(--t-exit) + var(--t-blend)) both;
  }
  ::view-transition-group(content) { animation-duration: calc(var(--t-exit) + var(--t-blend) + var(--t-enter)); }

  /* Navigation: completely still. The leaving page's navigation stays on screen, fully opaque,
     and the arriving page's navigation is kept hidden behind it until its fonts have loaded
     (head.js holds .vt-hold on <html> until then). Only then does the new one fade in on top.
     The two are identical apart from the highlighted link, so nothing moves: without the hold,
     the new navigation's first frames could be drawn before its fonts arrive and visibly jump.
     No size or position animation either. (Normal blending: the default plus-lighter would
     brighten two stacked opaque panels.) */
  ::view-transition-group(nav),
  ::view-transition-group(navbar) { animation: none; }
  ::view-transition-old(nav),
  ::view-transition-old(navbar) { animation: none; mix-blend-mode: normal; }
  ::view-transition-new(nav),
  ::view-transition-new(navbar) { animation: vt-fade-in 300ms ease both; mix-blend-mode: normal; }
  html.vt-hold::view-transition-new(nav),
  html.vt-hold::view-transition-new(navbar) { animation: none; opacity: 0; }

  /* Leaving from the open mobile menu (site.js fades the menu's links out first, leaving the
     Onyx sheet, then navigates; head.js sets .vt-from-menu on the arriving page). The old page
     is already hidden by the sheet, so: Onyx fades into the new background, then content in. */
  html.vt-from-menu::view-transition-old(root),
  html.vt-from-menu::view-transition-old(content) { display: none; }
  html.vt-from-menu::view-transition-new(root) { animation: none; }
  html.vt-from-menu::view-transition-old(menu-sheet) { animation: vt-fade-out var(--t-blend) ease-in-out both; }
  html.vt-from-menu::view-transition-new(content) { animation: vt-fade-in var(--t-enter) ease var(--t-blend) both; }
  html.vt-from-menu::view-transition-group(content) { animation-duration: calc(var(--t-blend) + var(--t-enter)); }

  @keyframes vt-fade-out { from { opacity: 1; } to { opacity: 0; } }
  @keyframes vt-fade-in  { from { opacity: 0; } to { opacity: 1; } }
}

/* ---------- Grain: code-generated noise, seamless tile ----------
   .grain on any element puts the noise above that element's own background
   and below its content, and grows with the element's height.
   The noise blends with the element's OWN background (the element is its own
   isolation group). On <body>, give <html> a background too, or the browser
   hands body's background to the canvas and the grain has nothing to blend
   with (it then just lightens the page). */
.grain { position: relative; isolation: isolate; }
.grain::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n' color-interpolation-filters='sRGB'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='.33 .33 .33 0 -.08 .33 .33 .33 0 -.08 .33 .33 .33 0 -.08 0 0 0 1 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: var(--grain-size) var(--grain-size);
  opacity: var(--grain-opacity);
  mix-blend-mode: var(--grain-blend);
}

/* ---------- Pill buttons & chips: optical centering ----------
   All pills set LT Sip caps with 0.2em tracking. Tracking adds a trailing gap after the
   last letter, and the caps sit high in the font's line box, so geometrically centered
   text reads left and high. text-indent matches the trailing gap; the top padding drops
   the caps onto the pill's center line. (body raises specificity over the page rules.) */
body :is(.btn-olive, .btn-granite, .rs-filters button, .ed-legend li) {
  text-indent: 0.2em;
  padding-top: 0.16em;
}

/* ---------- Scroll reveal ----------
   site.js tags text in <main> with data-reveal (opacity only).
   data-reveal="up" = fade + rise (per-instance exceptions in the guidelines).
   Put data-reveal on a wrapper to animate a group as one unit;
   data-reveal="none" opts an element (and its children) out. */
.js [data-reveal]:not([data-reveal="none"]) {
  opacity: 0;
  /* This rule outranks each element's own transition, so it also carries the site-wide
     hover fade (buttons and links tagged for reveal would otherwise snap on hover). */
  transition: opacity var(--reveal-dur) ease, transform var(--reveal-dur) ease,
    color var(--nav-hover-dur) ease, background-color var(--nav-hover-dur) ease,
    border-color var(--nav-hover-dur) ease, text-decoration-color var(--nav-hover-dur) ease;
  transition-delay: var(--reveal-delay, 0ms), var(--reveal-delay, 0ms), 0ms, 0ms, 0ms, 0ms;  /* stagger the reveal only, never the hover */
}
.js [data-reveal="up"] { transform: translateY(var(--reveal-shift)); }
.js [data-reveal].is-revealed { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1 !important; transform: none !important; transition: none !important; }
  .mobile-menu, .menu-sheet, .menu-toggle span { transition: none !important; }
}
