/* =========================================================
   PANTRY wireframe
   Base page, section rhythm, lines and type. Every value comes from
   tokens.css; columns come from grid.css, buttons and links from
   components.css. See DESIGN-SYSTEM.md.
   ========================================================= */

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  position: relative;
  background: var(--color-canvas);
  color: var(--color-ink);
  font-family: var(--font-sans);
  font-size: var(--text-body-size);
  font-weight: var(--text-body-weight);
  line-height: var(--text-body-lh);
  letter-spacing: var(--text-body-ls);
}

a {
  color: inherit;
}

ol,
ul {
  list-style: none;
}

/* ---------- Layout ----------
   Container, columns, cells and the grid overlay live in grid.css. */

.section {
  position: relative;
  padding: var(--section-pad) 0;
}

/* ---------- Section rhythm ----------
   Inside a section, vertical space comes only from these three tokens. */

.grid-12.section-grid {
  row-gap: 0;
}

.gap-title {
  margin-top: var(--space-label-title);
}

.gap-body {
  margin-top: var(--space-title-body);
}

.gap-cta {
  margin-top: var(--space-body-cta);
}


/* ---------- Structural lines ----------
   All lines and plus marks are measured from the same frame: the
   content box of .container. --x is a line's left edge in that frame. */

.frame {
  position: relative;
  height: 100%;
}

.marks {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
}

.marks .container {
  height: 100%;
}

/* The page-wide vertical lines are one canvas, drawn by scripts/lines.js.
   Fixed to the viewport (the lines are vertical, so it looks the same as a
   page-tall layer would) and behind everything, as the old .structure was. */
.lines {
  position: fixed;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* Zero-height copy of the layout container. lines.js measures it so the
   lines use the same frame as the content. */
/* The same lines again, on top of the dark principle stage (see principle.js). */
.lines-ink {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.lines-probe {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 0;
  visibility: hidden;
  pointer-events: none;
}

.at-0 { --x: 0%; }
.at-25 { --x: 25%; }
.at-50 { --x: 50%; }
.at-75 { --x: 75%; }
.at-100 { --x: calc(100% - var(--line-width)); }

/* Tablet: 2 bays. Mobile: outer edges only. Same set as --bays, which
   drives the canvas lines. These classes now place plus marks and the
   lines on the dark principle stage. */
@media (max-width: 1023px) {
  .at-25,
  .at-75 {
    display: none;
  }
}

@media (max-width: 639px) {
  .at-50 {
    display: none;
  }
}

.vline {
  position: absolute;
  top: 0;
  bottom: 0;
  left: var(--x);
  width: var(--line-width);
  background: var(--color-guide);
}

/* Horizontal lines: full viewport width, top and bottom of the section.
   The bottom line sits just below the section so it lands exactly on the
   next section's top line instead of doubling up. */
.has-lines::before,
.has-lines::after {
  content: "";
  position: absolute;
  z-index: -2;
  left: 0;
  right: 0;
  height: var(--line-width);
  background: var(--color-guide);
}

.has-lines::before {
  top: 0;
}

.has-lines::after {
  top: 100%;
}

/* Plus marks: centered on the crossing of a horizontal and a vertical line. */
.plus {
  --offset: calc((var(--plus-size) - var(--line-width)) / 2);
  position: absolute;
  left: calc(var(--x) - var(--offset));
  width: var(--plus-size);
  height: var(--plus-size);
  background:
    linear-gradient(var(--color-rule), var(--color-rule)) center / 100% var(--line-width) no-repeat,
    linear-gradient(var(--color-rule), var(--color-rule)) center / var(--line-width) 100% no-repeat;
}

.plus.top {
  top: calc(0% - var(--offset));
}

.plus.bottom {
  top: calc(100% - var(--offset));
}

/* ---------- Type ---------- */

.label {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--text-label-size);
  font-weight: var(--text-label-weight);
  line-height: var(--text-label-lh);
  letter-spacing: var(--text-label-ls);
  text-transform: uppercase;
  color: var(--color-text-secondary);
}

.display {
  font-size: var(--text-display-size);
  font-weight: var(--text-display-weight);
  line-height: var(--text-display-lh);
  letter-spacing: var(--text-display-ls);
}

.section-title {
  font-size: var(--text-section-size);
  font-weight: var(--text-section-weight);
  line-height: var(--text-section-lh);
  letter-spacing: var(--text-section-ls);
}

.item-title {
  font-size: var(--text-item-size);
  font-weight: var(--text-item-weight);
  line-height: var(--text-item-lh);
  letter-spacing: var(--text-item-ls);
}

.lead {
  font-size: var(--text-lead-size);
  font-weight: var(--text-lead-weight);
  line-height: var(--text-lead-lh);
  letter-spacing: var(--text-lead-ls);
  color: var(--color-text-secondary);
}

.caption,
.note {
  font-family: var(--font-mono);
  font-size: var(--text-caption-size);
  font-weight: var(--text-caption-weight);
  line-height: var(--text-caption-lh);
  color: var(--color-text-secondary);
}

.muted {
  color: var(--color-text-secondary);
}

.stack > * + * {
  margin-top: var(--space-16);
}

/* ---------- Image placeholder ---------- */

.placeholder {
  width: 100%;
  min-height: calc(var(--space-128) * 2);
  background: var(--color-surface-subtle);
  border: var(--line-width) solid var(--color-rule);
  border-radius: var(--radius);
}

.placeholder--small {
  min-height: var(--space-128);
}

.slot-image {
  display: block;
  width: 100%;
  height: auto;
}

/* ---------- Nav ---------- */

/* The header sticks to the top. At the top of the page it is see-through,
   so the hero's top line and plus marks show as before. Once the page has
   scrolled (.is-scrolled, set by render.js) it gets the canvas background,
   its own copy of the vertical lines and a hairline at its bottom edge. */
.nav {
  position: sticky;
  top: 0;
  z-index: 10;
  background: transparent;
}

.nav.is-scrolled {
  background: var(--color-canvas);
}

/* Over a full-screen pinned stage the header slides away (render.js). */
.nav {
  transition:
    background-color var(--nav-fade-duration) var(--ease),
    transform var(--nav-cta-duration) var(--ease),
    visibility 0s linear 0s;
}

.nav.is-yielding {
  transform: translate3d(0, -100%, 0);
  visibility: hidden;
  transition:
    background-color var(--nav-fade-duration) var(--ease),
    transform var(--nav-cta-duration) var(--ease),
    visibility 0s linear var(--nav-cta-duration);
}

@media (prefers-reduced-motion: reduce) {
  .nav.is-yielding {
    transform: none;
    opacity: 0;
  }

  .nav {
    transition:
      background-color var(--nav-fade-duration) var(--ease),
      opacity var(--nav-fade-duration) var(--ease),
      visibility 0s linear 0s;
  }

  .nav.is-yielding {
    transition:
      background-color var(--nav-fade-duration) var(--ease),
      opacity var(--nav-fade-duration) var(--ease),
      visibility 0s linear var(--nav-fade-duration);
  }
}

.nav-lines {
  position: absolute;
  inset: 0;
  z-index: -1;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--nav-fade-duration) var(--ease);
}

/* Sits just below the header, where the hero's top line is at rest. */
.nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: var(--line-width);
  background: var(--color-guide);
  opacity: 0;
  transition: opacity var(--nav-fade-duration) var(--ease);
}

.nav.is-scrolled .nav-lines,
.nav.is-scrolled::after {
  opacity: 1;
}

.nav > .container {
  position: relative;
}

/* Anchor jumps land below the sticky header. */
html {
  scroll-padding-top: var(--nav-height, 0px);
}

/* No border here: the line under the nav is the first section's top line,
   the same hairline as every other horizontal line. */
.nav-inner {
  align-items: center;
  padding: var(--space-16) 0;
}

.nav-logo {
  font-weight: var(--text-item-weight);
  text-decoration: none;
  white-space: nowrap;
}

.nav-actions {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: var(--space-8);
  min-width: 0;
}

/* Header buttons (components.css) stay on one line. */
.nav-actions .btn {
  white-space: nowrap;
}

/* ---------- Header CTA ----------
   The hero CTA, shown here once the hero CTA has scrolled away. Its space
   is always kept (left of the Menu button), so nothing moves when it comes
   and goes. Hidden it is also inert and aria-hidden (render.js). */
.nav-cta {
  pointer-events: none;
  opacity: 0;
  transform: translate3d(0, var(--nav-cta-rise), 0);
  transition:
    opacity var(--nav-fade-duration) var(--ease),
    transform var(--nav-cta-duration) var(--nav-cta-ease);
}

.nav-cta.is-shown {
  pointer-events: auto;
  opacity: 1;
  transform: none;
}

.nav-cta-short {
  display: none;
}

/* Mobile: the short label keeps logo, CTA and Menu on one row. */
@media (max-width: 639px) {
  .nav-cta-full {
    display: none;
  }

  .nav-cta-short {
    display: inline;
  }
}

@media (prefers-reduced-motion: reduce) {
  .nav-cta,
  .nav-cta.is-shown {
    transform: none;
  }
}

/* ---------- Menu panel ----------
   A band across the page under the header, built like a section: canvas
   background, its own copy of the page lines, hairlines and plus marks on
   its top and bottom edges. A mono title in the first bay, then one link
   per bay: the section's number in mono, its name in Libre Franklin.
   Red only on hover and focus. Opens with a reveal from the top, the links
   rising one after another on the site's spring; closes faster. */
.nav-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  isolation: isolate;
  padding-block: var(--menu-pad-block);
  background: var(--color-canvas);
  visibility: hidden;
  clip-path: inset(0 0 100% 0);
  transition:
    clip-path calc(var(--menu-open-duration) * 0.6) var(--ease),
    visibility 0s linear calc(var(--menu-open-duration) * 0.6);
}

.nav-panel.is-open {
  visibility: visible;
  clip-path: inset(0 0 calc(var(--plus-size) * -1) 0);
  transition:
    clip-path var(--menu-open-duration) var(--ease),
    visibility 0s linear 0s;
}

.nav-panel::before,
.nav-panel::after {
  content: "";
  position: absolute;
  z-index: -1;
  left: 0;
  right: 0;
  height: var(--line-width);
  background: var(--color-guide);
}

.nav-panel::before {
  top: 0;
}

.nav-panel::after {
  top: 100%;
}

.nav-panel-lines {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.grid-12.nav-panel-grid {
  align-items: start;
  row-gap: var(--space-32);
}

.l-menu-links {
  --d: 9;
  --t: var(--grid-columns-tablet);
  --m: var(--grid-columns-mobile);
}

/* Three links, one per bay (a bay is a third of these nine columns). */
.nav-panel-links {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}

.nav-panel-links li {
  opacity: 0;
  transform: translate3d(0, var(--nav-cta-rise), 0);
  transition:
    opacity calc(var(--menu-open-duration) * 0.5) var(--ease),
    transform calc(var(--menu-open-duration) * 0.5) var(--ease);
}

.nav-panel.is-open .nav-panel-links li {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--nav-cta-duration) var(--ease) calc(var(--i, 0) * var(--menu-item-stagger) + var(--menu-item-stagger)),
    transform var(--nav-cta-duration) var(--nav-cta-ease) calc(var(--i, 0) * var(--menu-item-stagger) + var(--menu-item-stagger));
}

.nav-panel-link {
  display: block;
  padding-inline: var(--cell-pad);
  color: var(--color-ink);
  text-decoration: none;
}

.nav-panel-number {
  margin-bottom: var(--space-12);
}

.nav-panel-name {
  display: block;
  font-size: var(--text-section-size);
  font-weight: var(--text-section-weight);
  line-height: var(--text-section-lh);
  letter-spacing: var(--text-section-ls);
  transition: color var(--nav-fade-duration) var(--ease);
}

.nav-panel-link:hover .nav-panel-name,
.nav-panel-link:focus-visible .nav-panel-name {
  color: var(--color-red-signal);
}

@media (prefers-reduced-motion: reduce) {
  .nav-panel,
  .nav-panel.is-open,
  .nav-panel-links li,
  .nav-panel.is-open .nav-panel-links li {
    transform: none;
    transition: none;
  }
}

/* ---------- Sections ---------- */

.step-number {
  margin-bottom: var(--space-12);
}

.step,
.case {
  padding-top: var(--space-16);
  border-top: var(--line-width) solid var(--color-rule);
}

/* Empty bays at the end of a card row (added by render.js) keep the top rule,
   so the row reads as one grid across the whole page. */
.lane-filler {
  border-top: var(--line-width) solid var(--color-rule);
}

.case .placeholder,
.case .slot-image {
  margin-bottom: var(--space-16);
}

/* Footer: see contact.css (contact and footer are one dark block). */
