/* layout.css: shell: container, nav, scroll progress, section frame, footer */

/* ---------- container ---------- */

.container {
  width: min(1200px, 100% - 2 * clamp(1rem, 4vw, 3rem));
  margin-inline: auto;
}

/* ---------- scroll progress ---------- */

.scroll-progress {
  display: none;
}

@supports (animation-timeline: scroll()) {
  .scroll-progress {
    display: block;
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    height: 3px;
    z-index: 200;
    background: var(--color-accent);
    transform: scaleX(0);
    transform-origin: left center;
    animation: scroll-progress-grow linear both;
    animation-timeline: scroll();
  }

  @keyframes scroll-progress-grow {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
  }
}

@media (prefers-reduced-motion: reduce) {
  .scroll-progress {
    animation: none;
    transform: scaleX(0);
  }
}

/* ---------- nav ---------- */

.site-nav {
  position: sticky;
  top: 0;
  z-index: 100;
  padding-block: var(--space-3);
  background: var(--color-surface-2);
  border-bottom: 1px solid var(--color-border-2);
}

@supports (backdrop-filter: blur(10px)) or (-webkit-backdrop-filter: blur(10px)) {
  .site-nav {
    background: color-mix(in srgb, var(--color-surface-2) 82%, transparent);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
  }
}

.site-nav-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
}

/* brand */

.brand {
  display: inline-flex;
  align-items: baseline;
  gap: 0;
  flex: none;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--color-text-hi);
  text-decoration: none;
  white-space: nowrap;
}

.brand:hover {
  text-decoration: none;
}

.brand-user {
  color: var(--color-accent);
}

.brand-path {
  color: var(--color-text-3);
}

.brand-cursor {
  margin-inline-start: 0.15em;
  color: var(--color-accent);
  animation: blink 1.06s step-end infinite;
}

@keyframes blink {
  50% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .brand-cursor {
    animation: none;
    opacity: 1;
  }
}

/* links */

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-mono);
  font-size: var(--step--1);
  min-width: 0;
}

.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--space-2);
  color: var(--color-text-2);
  text-decoration: none;
  white-space: nowrap;
  transition: color var(--dur-state) var(--ease-standard);
}

.nav-links a::before {
  content: './';
  color: var(--color-text-3);
}

.nav-links a:hover,
.nav-links a:focus-visible,
.nav-links a[aria-current] {
  color: var(--color-accent);
}

/* Persistent call to action. Once the hero scrolls away this is the only route to
   contact that stays on screen, so it lives in the sticky nav. Outlined rather than
   filled so it does not compete with the solid button in the hero. */

.nav-cta {
  flex: none;
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding-inline: var(--space-4);
  border: 1px solid var(--color-accent-dim);
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--color-accent);
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--dur-state) var(--ease-standard),
    border-color var(--dur-state) var(--ease-standard),
    color var(--dur-state) var(--ease-standard);
}

.nav-cta:hover,
.nav-cta:focus-visible {
  background-color: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-on-accent);
  text-decoration: none;
}

/* ---------- section shell ---------- */

.section {
  padding-block: var(--space-fluid-xl);
  scroll-margin-top: 5rem;
}

.hero {
  scroll-margin-top: 5rem;
}

.section-head {
  margin-bottom: var(--space-fluid-md);
}

.section-cmd {
  font-family: var(--font-mono);
  font-size: var(--step--1);
  color: var(--color-accent);
  margin: 0;
}

.section-cmd::before {
  content: '$\00a0';
  color: var(--color-text-3);
}

h2.section-title {
  font-size: var(--step-3);
  margin-top: var(--space-2);
}

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--color-border-2);
  background: var(--color-surface-1);
  font-family: var(--font-mono);
  font-size: var(--step--2);
  color: var(--color-text-3);
  padding-block: var(--space-4);
  padding-bottom: calc(var(--space-4) + env(safe-area-inset-bottom, 0px));
}

.site-footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-4);
}

/* the three spans need 798px of viewport to share one row (measured: 701px of text
   plus two 16px gaps inside a container that is 92% of the viewport). Below that they
   wrapped into two rows with an empty right half, so stack them instead. */

@media (max-width: 800px) {
  .site-footer-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ---------- narrow viewport and touch adjustments ---------- */

/* two row nav on narrow viewports */

@media (max-width: 860px) {
  .site-nav-inner {
    flex-wrap: wrap;
    gap: var(--space-2) var(--space-3);
  }

  /* row 1 keeps the brand and the action on opposite ends */
  .brand { order: 1; }
  .nav-cta { order: 2; }

  /* row 2: full width, links distributed */
  .nav-links {
    order: 3;
    flex-basis: 100%;
    justify-content: space-between;
    gap: 0;
  }

  .nav-links a {
    padding-inline: var(--space-1);
  }
}

/* One row again from 730px up. Measured on the live page: the brand, the four ./
   links and the chip stop fitting with var(--space-3) either side of the links at
   724px, so 730px keeps about 15px of clearance. This saves the second row on a
   768px tablet and on a 750px landscape phone, where the two row header was eating
   117px of a 342px screen. The second query extends the single row to 900px on
   short viewports, where a landscape phone has no height to spare. Below 730px the
   row no longer fits and the two row layout stands. */

@media (min-width: 730px) and (max-width: 860px),
       (min-width: 730px) and (max-width: 900px) and (max-height: 520px) {
  /* the single row is 44px of link height, so the base var(--space-3) block padding
     is no longer needed: var(--space-1) keeps the nav near 53px */
  .site-nav { padding-block: var(--space-1); }

  .site-nav-inner {
    flex-wrap: nowrap;
  }

  .brand { order: 0; }

  .nav-links {
    order: 1;
    flex-basis: auto;
    justify-content: flex-end;
    gap: var(--space-4);
  }

  .nav-cta { order: 2; }
}

/* the action stays on screen at every width. Measured at 320px the brand and
   the button together need about 275px of the 288px available, so it fits. */

@media (max-width: 360px) {
  .nav-cta {
    padding-inline: var(--space-3);
  }
}

/* on the narrowest phones the four links very nearly touch (measured 2px apart
   at 320px), which invites mis-taps. Dropping the ./ prefix here buys about 60px,
   spreading the gaps to roughly 24px. The terminal read is still carried by the
   brand prompt, the $ section commands and the mono type. */

@media (max-width: 360px) {
  .nav-links a::before { content: none; }
}

/* tighten nav height on phones */

@media (max-width: 640px) {
  .site-nav { padding-block: var(--space-1); }
  .nav-cta { min-height: 44px; }
}

/* safe area insets for notched phones */

@media (max-width: 900px) {
  .site-nav,
  .site-footer,
  .container {
    padding-inline: env(safe-area-inset-left, 0px) env(safe-area-inset-right, 0px);
  }

  /* the nav and footer shells already carry the inset, so their own container
     must not add it a second time */
  .site-nav-inner,
  .site-footer-inner {
    padding-inline: 0;
  }
}

/* short viewports (landscape phones). The trailing rhythm under the contact card is
   trimmed so the email and the button come to rest below the sticky nav at maximum scroll. */
@media (max-height: 520px) {
  .site-nav { padding-block: var(--space-1); }
  #contact { padding-bottom: 0; }
  .site-footer {
    padding-block: var(--space-1);
    padding-bottom: calc(var(--space-1) + env(safe-area-inset-bottom, 0px));
  }
}

/* the chip is a tap target on every touch device, including the one row bands
   above 640px where the phone block does not reach. It fits inside the 44px link row. */
@media (hover: none) and (pointer: coarse) {
  .nav-cta { min-height: 44px; }
}
