/* Work-in-progress portfolio page — Figma Portfolio_2023 / node 4863:1979.
   One fixed, non-scrolling viewport: a full-bleed blueprint grid with a white
   sheet whose edges snap to grid lines. Desktop values come from the 1280×832
   frame; mobile values are derived on a 24px grid. */

:root {
  --blue: #0022ff;
  --blue-soft: #8898ff;
  --grid-line: #4059ff;
  --paper: #ffffff;

  /* grid + frame geometry */
  --cell: 40px;
  --bx: 80px;          /* left/right band */
  --by: 40px;          /* top band */
  --by-end: 24px;      /* minimum bottom band; actual size absorbs the rounding */
  --corner-inset: 32px;
  --hair: 0.5px;       /* grid stroke, 1 device px on retina */
  --runway: 0px;       /* touch devices: scroll offset that lets Safari show the grid behind its bars */
  --bleed: 240px;      /* how far the grid runs past the bottom of the viewport */

  /* type */
  --font: "Outfit", "Helvetica Neue", Arial, sans-serif;
  --title-size: 3rem;          /* 48px */
  --sub-size: 1.25rem;         /* 20px */
  --contact-size: 1.125rem;    /* 18px */
  --art-w: 114px;

  --hero-gap: 20px;
  --contact-pad: 65px;
}

@media (max-resolution: 1.5dppx) {
  :root { --hair: 1px; --grid-line: #b3bcff; }
}

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

html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;      /* no-scroll page */
  overscroll-behavior: none;
}

/* Frame geometry lives on the root so the backdrop and the frame share it. */
html {
  /* bands never sit under a notch, status bar or home indicator */
  --sx: max(var(--bx), env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px));
  --st: max(var(--by), env(safe-area-inset-top, 0px));
  --sb: max(var(--by-end), env(safe-area-inset-bottom, 0px));
  --fw: calc(100vw - 2 * var(--sx));
  --fx: calc((100vw - var(--fw)) / 2);

  /* Safari 26 fills the strip behind its status bar / tab bar with this solid
     colour (it ignores background images there), so keep it the paper colour. */
  background-color: var(--paper);
}

@supports (width: round(down, 10px, 2px)) {
  html {
    --fw: round(down, 100vw - 2 * var(--sx), var(--cell));
    --fx: round(nearest, (100vw - var(--fw)) / 2, 1px);
  }
}

body {
  font-family: var(--font);
  font-weight: 300;
  color: var(--blue);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* ---- blueprint backdrop ----
   An ordinary absolutely-positioned layer, not position:fixed: iOS Safari 26
   paints normal page content underneath its floating tab bar but clips fixed
   layers at the bar's top edge. It runs past the bottom of the viewport so the
   grid shows through the bar. Origin = the frame's top-left, so the sheet's
   edges land on grid lines; the two blue layers continue the frame's vertical
   lines through the same area. */
.backdrop {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: calc(100% + var(--runway) + var(--bleed));
  pointer-events: none;
  touch-action: none;
  background-image:
    linear-gradient(var(--blue), var(--blue)),
    linear-gradient(var(--blue), var(--blue)),
    linear-gradient(to right, var(--grid-line) var(--hair), transparent var(--hair)),
    linear-gradient(to bottom, var(--grid-line) var(--hair), transparent var(--hair));
  background-size: 1px 100%, 1px 100%, var(--cell) var(--cell), var(--cell) var(--cell);
  background-repeat: repeat-y, repeat-y, repeat, repeat;
  background-position:
    var(--fx) 0,
    calc(var(--fx) + var(--fw)) 0,
    var(--fx) calc(var(--runway) + var(--st)),
    var(--fx) calc(var(--runway) + var(--st));
}

/* the visible viewport; no background of its own so Safari doesn't sample it */
.stage {
  position: fixed;
  inset: 0;
  overflow: hidden;
}

/* ---- frame: snaps to whole grid cells, centred horizontally ---- */
.frame {
  --fh: calc(100% - var(--st) - var(--sb));
  position: absolute;
  top: var(--st);
  left: var(--fx);
  width: var(--fw);
  height: var(--fh);
}

@supports (width: round(down, 10px, 2px)) {
  .frame { --fh: round(down, 100% - var(--st) - var(--sb), var(--cell)); }
}

.sheet {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 0 24px;
  background: var(--paper);
  /* only scrolls if content can't fit (huge browser font sizes, tiny windows) */
  overflow-x: hidden;
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* full-bleed frame lines (they run through the bands to the viewport edge) */
.frame::before,
.frame::after {
  content: "";
  position: absolute;
  z-index: 2;
  pointer-events: none;
}
.frame::before {
  top: 0;
  height: calc(100% + 1px);
  left: -100vw;
  right: -100vw;
  border-top: 1px solid var(--blue);
  border-bottom: 1px solid var(--blue);
}
.frame::after {
  left: 0;
  width: calc(100% + 1px);
  top: -100vh;
  bottom: -100vh;
  border-left: 1px solid var(--blue);
  border-right: 1px solid var(--blue);
}

/* ---- corner marks ---- */
.corner {
  position: absolute;
  width: 12px;
  height: 12px;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M6 .7 11.3 6 6 11.3.7 6Z' fill='none' stroke='%230022ff'/%3E%3Cpath d='M6 3.6 8.4 6 6 8.4 3.6 6Z' fill='%230022ff'/%3E%3C/svg%3E") center / contain no-repeat;
}
.corner--tl { top: var(--corner-inset); left: var(--corner-inset); }
.corner--tr { top: var(--corner-inset); right: var(--corner-inset); }
.corner--bl { bottom: var(--corner-inset); left: var(--corner-inset); }
.corner--br { bottom: var(--corner-inset); right: var(--corner-inset); }

/* ---- hero ---- */
.hero {
  max-width: 100%;
  margin-block: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}

.hero__art {
  display: block;
  width: var(--art-w);
  height: auto;
  margin-bottom: var(--hero-gap);
}

.hero__title {
  margin: 0;
  font-size: var(--title-size);
  font-weight: 200;
  line-height: 1.2;
  letter-spacing: -0.043em;
  overflow-wrap: break-word;
}

.hero__sub {
  max-width: 20em;
  margin: 7px 0 0;
  font-size: var(--sub-size);
  font-weight: 200;
  line-height: 1.25;
  letter-spacing: -0.06em;
  color: var(--blue-soft);
}

/* ---- contact ---- */
.contact {
  max-width: 100%;
  padding-bottom: var(--contact-pad);
  text-align: center;
  font-size: var(--contact-size);
  letter-spacing: -0.014em;
}

.contact__label {
  margin: 0;
  font-weight: 200;
  color: var(--blue-soft);
}

.contact__email {
  display: inline-block;
  max-width: 100%;
  overflow-wrap: anywhere;
  padding: 4px 6px;
  border-radius: 4px;
  color: var(--blue);
  font-weight: 300;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
  transition: text-decoration-color .2s ease;
}
.contact__email:hover { text-decoration-color: currentColor; }
.contact__email:focus-visible {
  outline: 1px solid var(--blue);
  outline-offset: 2px;
  text-decoration-color: currentColor;
}

/* ---- touch devices: Safari 26 "scroll runway" ----
   iOS Safari only paints page content behind its status bar and floating tab
   bar when the document is scrollable and scrolled. So on touch screens the
   document is a little taller than the viewport, the stage sits below a short
   runway, and main.js scrolls past it on load and holds it there. Pans are
   blocked on the stage; the sheet only accepts them when it actually overflows. */
@media (hover: none) and (pointer: coarse) {
  :root { --runway: 62px; }
  html {
    overflow-x: hidden;
    overflow-y: scroll;
  }
  body {
    height: auto;
    min-height: calc(100dvh + var(--runway) + var(--bleed));
    overflow: visible;
  }
  .stage {
    position: relative;
    inset: auto;
    height: 100vh;
    height: 100dvh;
    margin-top: var(--runway);
    touch-action: none;   /* taps still work; pans can't move the page */
  }
  .sheet { touch-action: none; }
  .sheet.is-scrollable { touch-action: pan-y; }
}

/* ---- mobile: tighter 24px grid ---- */
@media (max-width: 767px) {
  :root {
    --cell: 24px;
    --bx: 24px;
    --by: 48px;
    --by-end: 32px;
    --corner-inset: 16px;
    --title-size: clamp(1.75rem, 8.6vw, 2.5rem);
    --sub-size: 1.0625rem;
    --contact-size: 1.0625rem;
    --art-w: 96px;
    --hero-gap: 24px;
    --contact-pad: 48px;
  }
  .corner { width: 10px; height: 10px; }
  .hero__sub { max-width: 17em; text-wrap: balance; }
}

/* ---- short viewports (landscape phones, small laptop windows) ---- */
@media (max-height: 620px) {
  :root {
    --art-w: 72px;
    --hero-gap: 14px;
    --title-size: 2.125rem;
    --sub-size: 1rem;
    --contact-size: 1rem;
    --contact-pad: 28px;
    --corner-inset: 16px;
  }
  @media (max-width: 767px) {
    :root { --by: 24px; --by-end: 16px; }
  }
}

@media (max-height: 440px) {
  :root { --art-w: 56px; --hero-gap: 10px; --title-size: 1.75rem; --contact-pad: 20px; }
  .hero__sub { display: none; }
}

/* tiny windows: keep breathing room once the sheet starts scrolling */
@media (max-height: 320px) {
  .hero { margin-block: 24px 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .contact__email { transition: none; }
}
