/* Shared by every Plot Joinery page: colours, typeface, page transitions, header and footer.
   Side margins come from --edge / --edge-r (set by assets/layout.js) so everything lines up with the cabinet run. */

/* Helvetica Neue where installed (Mac, iPhone, iPad); Helvetica / Arial elsewhere */
/* No rubber-band bounce past the top or bottom of the page: on iPhones the bounce dragged the page under the
   fixed header and made everything look jittery */
html { overscroll-behavior-y: none; scrollbar-gutter: stable; }   /* same page width with or without a scrollbar */
/* No double-tap zoom: tapping the menu button quickly on iPhones zoomed the page. Pinch-zoom still works */
html { touch-action: manipulation; }

:root {
  --paper: #f6f5f2; --ink: #1c1a17; --line: rgba(28, 26, 23, .55); --yellow: #fff56d;
  --sans: "Helvetica Neue", Helvetica, Arial, sans-serif;
  --header-h: 77px;
}

/* ---------- Page transitions ---------- */
/* A quick crossfade. Headings don't glide between pages: they simply fade with the page */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 350ms; }
body :is(h1, .handover, .project-title, [data-t]) { view-transition-name: none !important; }
/* Projects: the clicked photo grows into the project page's lead photo */
::view-transition-group(project-image) { animation-duration: 550ms; animation-timing-function: cubic-bezier(.2, .7, .2, 1); }
::view-transition-old(project-image), ::view-transition-new(project-image) { height: 100%; object-fit: cover; }
/* The header is identical on every page, so it is locked: no movement and no fade, it simply stays put */
::view-transition-group(site-header), ::view-transition-new(site-header) { animation: none; }
::view-transition-old(site-header) { display: none; }
/* Phones: just a quick, plain crossfade between pages. No gliding heading or growing photo (they stuttered on
   phones), so every element except the locked header fades with the page. Back/forward swipes skip it (layout.js). */
@media (max-width: 767px) {
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 200ms; }
  body :not(.site-header) { view-transition-name: none !important; }   /* (not the page itself, which does the fade) */
}

/* ---------- Header: fixed to the top of every page, in exactly the same place ---------- */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 10;
  display: flex; align-items: center; justify-content: space-between;
  padding: 20px var(--edge-r, 40px) 20px var(--edge, 40px);
  view-transition-name: site-header;
}
.site-header.solid { background: var(--paper); }   /* inner pages: content scrolls underneath */
/* The logo scales with the window: 27px on a large monitor (1900px+ wide), down to 19.5px on a smaller laptop.
   (The header keeps its height, set by the button, so nothing else on the page moves.) */
.site-header img { height: clamp(19.5px, 1.425vw, 27px); width: auto; display: block; }   /* 25% smaller than it was */
.quote {
  display: inline-block; font-family: var(--sans); font-size: 14px; font-weight: 500;
  background: var(--ink); color: var(--paper); padding: 10px 20px; border-radius: 999px; text-decoration: none;
  white-space: nowrap;   /* never wrap onto two lines (it did in narrow footer and contact columns) */
}
.quote:hover { opacity: .85; }
/* The header's button is lighter: dark outline and text, no fill; on hover it fills black with yellow text */
.site-header .quote { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); transition: background .2s, color .2s; }
.site-header .quote:hover { opacity: 1; background: var(--ink); color: var(--yellow); }
/* On the Work with us page the button would lead to the page you're already on, so it's greyed out. Hovering or
   clicking it shows a small note instead of reloading the page (assets/menu.js) */
.site-header .quote[aria-current] { position: relative; overflow: visible; cursor: default;
  color: rgba(28, 26, 23, .35); background: transparent; box-shadow: inset 0 0 0 1px rgba(28, 26, 23, .3); }
.quote[aria-current]::after { content: attr(data-tip); position: absolute; left: 50%; top: calc(100% + 10px); z-index: 20;
  transform: translate(-50%, -4px); padding: 7px 12px; border-radius: 8px; background: var(--ink); color: var(--paper);
  font-size: 13px; font-weight: 400; white-space: nowrap; pointer-events: none; opacity: 0; transition: opacity .15s, transform .15s; }
.quote[aria-current]:hover::after, .quote[aria-current].tip-show::after { opacity: 1; transform: translate(-50%, 0); }
@media (hover: none) { .quote[aria-current]:hover::after { opacity: 0; } .quote[aria-current].tip-show::after { opacity: 1; } }

/* Page links in the header, leading into the button. The page you're on sits in a yellow block; the others are
   softened (still easy to read) and darken on hover. (Phones use the menu in assets/menu.js instead.) */
.header-right { display: flex; align-items: center; gap: 14px; }
.site-nav { display: flex; gap: 6px; font-family: var(--sans); font-size: 14px; font-weight: 500; }
.site-nav a { color: var(--ink); text-decoration: none; padding: 6px 10px; border-radius: 4px; opacity: .62; transition: opacity .2s; }
.site-nav a:hover, .site-nav a:focus-visible { opacity: 1; }
.site-nav a[aria-current] { opacity: 1; background: var(--yellow); }

/* Inner pages fill at least the whole screen, so the footer always starts below the fold, even on short pages
   like Contact and Careers. (lvh: the screen's full height on phones, with the browser bars hidden.) */
.site-header.solid ~ main { box-sizing: border-box; min-height: 100vh; min-height: 100lvh; }

/* The same space under every page heading, down to whatever comes first (a divider line, photos or boxes).
   (Not where a line of intro text follows the heading.) */
main > h1:not(:has(+ .intro)) { margin-bottom: 48px !important; }
main > h1:not(:has(+ .intro)) + * { margin-top: 0 !important; }
@media (max-width: 767px) { main > h1:not(:has(+ .intro)) { margin-bottom: 32px !important; } }

/* Photo frames: a plain warm tone while a photo loads (not the crossed-out placeholder), then the photo fades in.
   (assets/layout.js marks each photo once it has loaded; without JavaScript photos simply show as normal.) */
.img, .thumb { background: #ebe9e4 !important; }
.js .img > img, .js .thumb > img { opacity: 0; transition: opacity .4s ease, transform 1.4s cubic-bezier(.2, .7, .2, 1); }   /* (keeps the slow hover push-in) */
.js .img > img.is-loaded, .js .thumb > img.is-loaded { opacity: 1; }

/* Keyboard focus: a thin ring around whatever the Tab key has reached (links, buttons, form fields), in the same
   ink as the button outline. Only shown when using the keyboard, never on mouse clicks or taps. */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.site-footer :focus-visible { outline-color: var(--yellow); }   /* on the dark footer */

/* ---------- Footer: quick links to every page, plus contact details. Dark, with the yellow logo. ---------- */
.site-footer {
  position: relative; z-index: 7;
  background: var(--ink); color: var(--paper); font-family: var(--sans);
  padding: 64px var(--edge-r, 40px) 32px var(--edge, 40px);
}
/* Strict six-column grid, one column per cabinet door, spanning exactly the width of the run */
.site-footer .footer-grid { display: grid; grid-template-columns: repeat(6, 1fr); column-gap: 0; align-items: start; }
.site-footer .footer-brand { grid-column: 1 / 3; }
.site-footer .footer-pages { grid-column: 3 / 4; }
.site-footer .footer-contact { grid-column: 4 / 6; }
.site-footer .footer-cta { grid-column: 6 / 7; justify-self: end; }   /* ends on the header button's edge */
.site-footer img { height: 32px; width: auto; display: block; }
.site-footer .tagline { margin: 16px 0 0; font-size: 15px; line-height: 1.5; white-space: nowrap; opacity: .7; }
.site-footer ul { list-style: none; margin: 0; padding: 0; font-size: 15px; line-height: 1.6; }
.site-footer li + li { margin-top: 4px; }
.site-footer a:not(.quote) { color: inherit; text-decoration: none; }
.site-footer ul a:hover { text-decoration: underline; text-underline-offset: 3px; }
.site-footer .social { display: inline-block; margin-top: 20px; opacity: .85; }
.site-footer .social:hover { opacity: 1; }
.site-footer .social svg { display: block; }
.site-footer .quote { background: var(--yellow); color: var(--ink); }
.site-footer .footer-base { margin-top: 56px; font-size: 13px; opacity: .55; }

/* Tablets and small laptops: six footer columns are too tight (the tagline ran into the page links), so the logo
   and tagline get their own row and the links, contact details and button share the row below */
@media (min-width: 768px) and (max-width: 1099px) {
  .site-footer .footer-grid { grid-template-columns: repeat(3, 1fr); row-gap: 36px; }
  .site-footer .footer-brand { grid-column: 1 / -1; }
  .site-footer .footer-pages { grid-column: 1 / 2; }
  .site-footer .footer-contact { grid-column: 2 / 3; }
  .site-footer .footer-cta { grid-column: 3 / 4; }
}

@media (max-width: 767px) {
  :root { --header-h: 61px; }
  .site-header { padding-top: 16px; padding-bottom: 16px; }
  .site-header img { height: 28px; }
  .site-footer { padding-top: 48px; }
  /* Phones: one column (the email address is too long to share a row) */
  .site-footer .footer-grid { grid-template-columns: 1fr; row-gap: 32px; }
  .site-footer .footer-grid > * { grid-column: 1 / -1; justify-self: center; text-align: center; }
  .site-footer .footer-brand img { margin: 0 auto; }   /* logo is a block, so centre it directly */
  .site-footer .tagline, .site-footer .footer-pages { display: none; }   /* phones: logo, contact, Instagram, button, copyright only */
  .site-footer .footer-base { text-align: center; }
}

/* ---------- Menu (assets/menu.js): phones and tablets, where the page links don't fit in the header ---------- */
.menu-btn, .site-menu { display: none; }
/* The header links replace the back arrow (and "All projects") everywhere */
main a.back { display: none !important; }
main > a.back + h1 { margin-top: 40px; }
@media (min-width: 768px) {
  .project-page .aside { top: calc(var(--header-h) + 16px); max-height: calc(100svh - var(--header-h) - 16px); padding-top: 16px; }
}
/* Small laptops: tighter spacing so all six links still fit beside the button */
@media (min-width: 1000px) and (max-width: 1099px) {
  .header-right { gap: 10px; }
  .site-nav { gap: 0; }
  .site-nav a { padding: 6px 7px; }
}
@media (max-width: 767px) {
  .site-header.solid .quote { display: none; }   /* phones: "Discuss your project" lives in the menu and at the end of each page */
  /* Project pages: the lead photo comes first, then the name and details, then the rest of the photos */
  .project-page .split { display: flex; flex-direction: column; align-items: stretch; padding-top: 16px; }
  .project-page .photos { display: contents; }
  .project-page .photos > .hero { order: 0; margin-bottom: 28px; }
  .project-page .aside { order: 1; }
  .project-page .photos > .seq { order: 2; }
  .project-page .seq, .project-page .pair, .project-page .trio, .project-page .details { gap: var(--edge, 16px); }   /* gap between photos = side margin */
}
@media (max-width: 999px) {
  .site-nav { display: none; }
  .header-right { gap: 12px; }
  /* 44px tap target, but the negative margins keep the header the same height as before */
  .menu-btn { display: grid; place-content: center; gap: 7px; width: 44px; height: 44px; margin: -8px -10px -8px 0;
              padding: 0; border: 0; background: none; color: var(--ink); cursor: pointer; -webkit-tap-highlight-color: transparent; }
  .menu-btn span { display: block; width: 24px; height: 2px; background: currentColor; border-radius: 1px; transition: transform .3s cubic-bezier(.2, .7, .2, 1); }
  .menu-open .menu-btn span:first-child { transform: translateY(4.5px) rotate(45deg); }
  .menu-open .menu-btn span:last-child { transform: translateY(-4.5px) rotate(-45deg); }
  /* Slides down under the header (which stays put, so the logo and the close button remain) */
  .site-menu { display: flex; flex-direction: column; position: fixed; inset: 0; z-index: 9; overflow-y: auto;
               padding: var(--header-h) var(--edge-r, 16px); background: var(--paper); align-items: center; justify-content: center; text-align: center;
               visibility: hidden; opacity: 0; transform: translateY(-16px);
               transition: opacity .25s ease, transform .35s cubic-bezier(.2, .7, .2, 1), visibility 0s linear .35s; }
  .menu-open .site-menu { visibility: visible; opacity: 1; transform: none; transition: opacity .25s ease, transform .35s cubic-bezier(.2, .7, .2, 1); }
  .menu-open, .menu-open body { overflow: hidden; }
  .menu-instant .site-menu, .menu-instant .menu-btn span { transition: none !important; }
  .site-menu ul { list-style: none; margin: 0 0 36px; padding: 0; }
  .site-menu li a { display: block; padding: 6px 0; font-size: 40px; line-height: 1.1; font-weight: 500; letter-spacing: -.015em; color: var(--ink); text-decoration: none; }
  .site-menu li a[aria-current] { opacity: .4; }
  .site-menu .quote { align-self: center; font-size: 15px; padding: 14px 28px; }
}

/* ---------- Loader: the full stop from "plot.", three dots lifting in a wave ----------
   From the design handoff "Plot dots loader". Sized by height (2.2:1); takes the text colour.
   Markup: <svg class="plot-dots" viewBox="0 0 660 300" role="img" aria-label="Loading"><circle cx="110" cy="200" r="86"/>
           <circle cx="330" cy="200" r="86"/><circle cx="550" cy="200" r="86"/></svg> */
.plot-dots { height: 1em; width: auto; fill: currentColor; overflow: visible; display: block; }
.plot-dots circle { animation: plot-wave 1.4s cubic-bezier(.45, 0, .55, 1) infinite both; transform-box: fill-box; transform-origin: center; }
.plot-dots circle:nth-child(2) { animation-delay: .16s; }
.plot-dots circle:nth-child(3) { animation-delay: .32s; }
@keyframes plot-wave { 0%, 50%, 100% { transform: translateY(0); } 25% { transform: translateY(-60%); } }
@media (prefers-reduced-motion: reduce) {
  .plot-dots circle { animation: plot-calm 1.6s ease-in-out infinite both; }
  @keyframes plot-calm { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
}
