/* robertpecina.com — minimal landing */

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

@font-face {
    font-family: 'ABC Marfa';
    src: url('/font/ABCMarfa-Thin.woff2') format('woff2');
    font-weight: 100;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'ABC Marfa';
    src: url('/font/ABCMarfa-Regular.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}

:root {
    --bg: #fff;
    --fg: #000;
    --muted: #6a6a6a;      /* 5.4:1 on white — AA with headroom; the dark page overrides to #8a8a8a below */
    --grid-v: rgba(0, 0, 0, 0.06);
    --pad: clamp(20px, 3.2vw, 48px);
    --rhythm: clamp(1.5rem, 0.99rem + 0.525vw, 2.25rem);   /* vertical baseline module = body leading (1.5×); fluid so the grid scales with the type at 4K, flat (1.5rem) on normal desktops */
    --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

html { -webkit-text-size-adjust: 100%; overscroll-behavior-y: none; }

body {
    background: var(--bg);
    color: var(--fg);
    font-family: 'ABC Marfa', 'Helvetica Neue', Helvetica, Arial, sans-serif;
    font-weight: 400;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

a { color: inherit; text-decoration: none; }

/* Keyboard-only focus ring — brand ink, invisible to mouse users (:focus-visible).
   var(--fg) is #000 on light pages, #fff on the dark page, so the ring always
   contrasts its background. The existing `outline: none` rules on .statement,
   .doc-title, and the newsletter input out-specify this universal rule, so the
   ring lands only on real interactive controls (links, the Subscribe button). */
:focus-visible { outline: 2px solid var(--fg); outline-offset: 3px; }

.skip-link {
    position: absolute;
    top: 0.75rem;
    left: 0.75rem;
    z-index: 10;
    padding: 0.5rem 0.75rem;
    background: #fff;
    color: #000;
    font-size: 0.8125rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    transform: translateY(-300%);
}
.skip-link:focus { transform: none; }

.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ── BASE END ── */

#wrapper { position: relative; min-height: 100svh; overflow: clip; }

/* ── Page frame: one viewport, three rows ── */
.page {
    min-height: 100svh;
    display: grid;
    grid-template-rows: auto 1fr;
    padding: var(--pad);
    padding-bottom: calc(var(--pad) + env(safe-area-inset-bottom, 0px));
    color: var(--fg);
    background-color: var(--bg);
    background-image: linear-gradient(90deg, var(--grid-v) 1px, transparent 1px);
    background-size: 25% 100%;
    background-origin: content-box; /* lines land on content quarters — type sits on them */
}
.page--dark {
    --bg: #000;
    --fg: #fff;
    --muted: #8a8a8a;      /* 6:1 on black — AA with headroom (light pages use #6a6a6a) */
    --grid-v: rgba(255, 255, 255, 0.10);
}

/* Dark page: paint the document + body black too, so iOS Safari's overscroll
   rubber-band never flashes the white body behind the black page. :has() re-
   evaluates when the router swaps a light/dark .page in — no JS needed. */
html:has(.page--dark), body:has(.page--dark) { background: #000; }
.page.is-entering { position: fixed; inset: 0; z-index: 2; }  /* viewport-locked so a scrolled-down leaving page can't offset it */
.page.is-leaving  { z-index: 1; }

/* ── Header ── */
.site-head {
    display: grid;
    grid-template-columns: repeat(4, 1fr); /* mirrors the background grid */
    align-items: baseline;
    font-size: clamp(0.8125rem, 0.4rem + 0.36vw, 1.25rem);  /* 13px on normal desktops, grows to ~20px (≈ statement/5) on 4K */
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.site-head a { white-space: nowrap; display: inline-block; padding: 0.75rem 0; margin: -0.75rem 0; }
/* The wordmark sits ~6px above the role subtitle, so a ring wrapping its full
   vertical tap-padding slices through "Director of Digital Experience". Drop the
   BOTTOM tap-padding only — the ring then hugs the name, while the top padding
   keeps the tap target ≥24px. Net layout is unchanged (the negative margin had
   already zeroed the bottom footprint). */
.site-head .wordmark { padding-bottom: 0; margin-bottom: 0; }
.site-head .nav-link { grid-column: 4; justify-self: start; }  /* 4th column (75% line) — aligns above the Privacy link */
.site-id { display: grid; gap: 0.125rem; }
.site-role { color: var(--muted); white-space: nowrap; }
.nav-link .return { color: var(--muted); margin-left: 0.35em; transition: color 0.3s var(--ease); }
.nav-link:hover .return { color: var(--fg); }
.nav-link { color: var(--muted); transition: color 0.3s var(--ease); }
.nav-link:hover { color: var(--fg); }

/* ── Body: vertically centered ── */
.page-body {
    align-self: center;
    display: grid;
    gap: clamp(2.5rem, 6vh, 4.5rem);
}

.statement {
    font-weight: 100;
    font-size: clamp(2.25rem, 5.4vw, 6rem);
    line-height: 1.1;
    letter-spacing: -0.02em;
    text-indent: 25%; /* first line starts on the second grid line */
}
.statement:focus { outline: none; }

/* Inline venture links: underlined, with a small external-link mark */
.statement a {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 0.14em;
    text-decoration-color: #bbb;
    transition: text-decoration-color 0.3s var(--ease);
}
.statement a:hover { text-decoration-color: var(--fg); }
.statement .ext {
    font-size: 0.4em;
    vertical-align: 0.95em;
    margin-left: 0.1em;
    color: var(--muted);
}

/* ── Contact ── */
.statement--contact {
    font-size: clamp(1.375rem, 7.4vw, 6rem);
    white-space: nowrap;
    text-indent: 0;
}
.statement--contact a { text-decoration: none; }
.statement--linkedin a { color: var(--muted); transition: color 0.3s var(--ease); }
.statement--linkedin a:hover { color: var(--fg); }

/* ── Ultra-wide: end the paragraph on the 75% grid line so it holds ~3
      lines instead of 2; indent is 25%-of-content = 1/3 of this 75% box ── */
@media (min-width: 2800px) {
    .statement { max-width: 75%; text-indent: 33.3333%; }
    .statement--contact { max-width: none; text-indent: 0; }
}

/* ── Mobile: the page becomes header / content / footer grid rows;
      the nav is the footer — first column, on the frame's bottom line ── */
@media (max-width: 640px) {
    /* stack: name/title · nav link · statement (fills) · Privacy Policy */
    .page { grid-template-rows: auto auto 1fr auto; }
    /* display:contents removes the box but keeps inheritance — children get
       the font-size from .site-head (desktop's 4-col template is inert here) */
    .site-head { display: contents; font-size: 0.875rem; }
    .site-head .site-id { grid-row: 1; }
    .site-head .nav-link {
        grid-column: 1;
        grid-row: 2;                          /* directly under the name/title, above the statement */
        justify-self: start;
        margin-top: clamp(2rem, 6vh, 3rem);   /* space between the title and the nav link */
        text-decoration: underline;
        text-decoration-thickness: 1px;
        text-underline-offset: 0.25em;
        text-decoration-color: var(--muted);
    }
    .page-body { grid-row: 3; }               /* statement fills the middle */
}

/* ── Venture preview panel (desktop hover) ──────────────────────────────── */
.preview-panel {
    position: fixed;
    top: 0; left: 0;
    z-index: 5;
    visibility: hidden;            /* GSAP autoAlpha toggles visibility + opacity */
    opacity: 0;
    pointer-events: none;          /* decorative — never intercepts the cursor */
    will-change: transform, opacity, filter;
}
.preview-shot {
    width: clamp(320px, 34vw, 460px);
    aspect-ratio: 16 / 10;
    overflow: hidden;
    background: var(--bg);
    border: 1px solid var(--grid-v);
    box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.35);
}
.preview-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; display: block; }
/* RP Studio: a pile of prints, cycled one at a time (js drives the shuffle).
   The stack is a fixed frame; each card is uniform "photo stock" and the image
   sits inside at its native aspect (object-fit: contain) — so the pile reads as
   a tidy stack while every photo, portrait or landscape, is shown whole. */
.preview-stack {
    position: relative;
    width: 256px;
    height: 320px;
}
.preview-card {
    position: absolute;
    inset: 0;
    padding: 6px;                 /* slim white print border around the photo */
    background: var(--bg);
    border: 1px solid var(--grid-v);
    box-shadow: 0 10px 26px -12px rgba(0, 0, 0, 0.45);
    will-change: transform, opacity;
    backface-visibility: hidden;
}
.preview-card img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* ── Newsletter (contact) ───────────────────────────────────────────────── */
.newsletter { margin-top: clamp(2rem, 5vh, 3.5rem); width: 25%; min-width: 18rem; }  /* fills the first column — right edge on the 25% grid line; wide enough for a one-line intro on large displays */
.newsletter-intro { color: var(--muted); font-size: clamp(0.95rem, 0.77rem + 0.37vw, 1.65rem); margin-bottom: calc(var(--rhythm) * 0.5); }  /* on the baseline half-module (was 0.9rem ≈ 0.6×) */
.newsletter-form { display: flex; align-items: baseline; gap: 0.75rem; border-bottom: 1px solid var(--muted); padding-bottom: 0.5rem; transition: border-color 0.3s var(--ease); }
.newsletter-form input { flex: 1; min-width: 0; background: transparent; border: 0; color: var(--fg); font: inherit; font-size: clamp(1.1rem, 0.77rem + 0.37vw, 1.65rem); padding: 0.25rem 0; }
.newsletter-form input::placeholder { color: var(--muted); }
.newsletter-form input:focus { outline: none; }
.newsletter-form:focus-within { border-bottom-color: var(--fg); } /* visible focus indicator (WCAG 2.4.7) — the input's own outline is removed */
.newsletter-form button { background: transparent; border: 0; color: var(--muted); font: inherit; font-size: clamp(0.8125rem, 0.4rem + 0.36vw, 1.25rem); text-transform: uppercase; letter-spacing: 0.06em; white-space: nowrap; cursor: pointer; transition: color 0.3s var(--ease); }
.newsletter-form button:hover:not(:disabled) { color: var(--fg); }
.newsletter-form button:disabled { opacity: 0.5; cursor: default; }
.newsletter-consent { color: var(--muted); font-size: clamp(0.8125rem, 0.4rem + 0.36vw, 1.25rem); margin-top: 0.75rem; }
.newsletter-consent a { text-decoration: underline; text-decoration-color: var(--muted); text-underline-offset: 0.2em; }
.newsletter-note { color: #e5484d; font-size: clamp(0.875rem, 0.5rem + 0.36vw, 1.3rem); margin-top: calc(var(--rhythm) * 0.5); }  /* stacked below the form (see note() in app.js); rouge reads as an error, not body copy — AA (5.4:1) on the black contact page */
.newsletter-done { color: var(--fg); font-weight: 100; font-size: clamp(0.95rem, 0.77rem + 0.37vw, 1.65rem); margin-top: calc(var(--rhythm) * 0.5); }  /* replaces the form in place — same half-module gap below the intro, so the centered block doesn't jump on confirm */

/* ── Privacy (doc page): a Swiss grid, not a loose flow ──────────────────────
   Horizontal — columns snap to the page's 25% background grid. Type is flush-left
   to the 0/25/50/75 lines; gutters are INTERNAL padding-right so the column edge
   itself always lands on a line (a plain grid `gap` would push edges off the grid).
   The three text fields occupy 0–75%; the fourth field is deliberate negative
   space (an asymmetric grid). Vertical — every gap is a multiple of
   the --rhythm baseline module (= body leading), so the page reads on one ruler. */
.page--doc .page-body { align-self: safe center; display: block; }   /* vertically centered like the pager pages when it fits; `safe` falls back to top-aligned if the content is taller than the space (never overflows into the header). Horizontal stays on the left grid line. Mobile restores an explicit gap below the nav — see ≤640. */
.doc-title { font-weight: 100; font-size: clamp(2rem, 4vw, 3rem); letter-spacing: -0.02em; }
.doc-title:focus { outline: none; }
.doc-meta { color: var(--muted); font-size: clamp(0.8125rem, 0.4rem + 0.36vw, 1.25rem); text-transform: uppercase; letter-spacing: 0.06em; margin-top: calc(var(--rhythm) * 0.5); }
.doc-intro { font-size: clamp(1rem, 0.66rem + 0.35vw, 1.5rem); line-height: 1.5; max-width: 52ch; margin-top: calc(var(--rhythm) * 2); }
/* the six topical sections flow into columns (2 up, 3 on wide screens); each
   section stays whole (break-inside) so a heading never orphans from its text.
   column-gap:0 keeps track edges on the grid lines — the gutter is padding-right. */
.doc-grid { display: grid; grid-template-columns: repeat(2, 50%); column-gap: 0; row-gap: calc(var(--rhythm) * 2); margin-top: calc(var(--rhythm) * 2); }
.doc-section { break-inside: avoid; padding-right: var(--rhythm); }
.doc-section h2 { font-weight: 400; font-size: clamp(1.05rem, 0.7rem + 0.36vw, 1.55rem); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: calc(var(--rhythm) * 0.5); }
.doc-section p { font-size: clamp(1rem, 0.66rem + 0.35vw, 1.5rem); line-height: 1.5; max-width: 54ch; }   /* measure cap only bites at 4K, where a 25% column gets very wide */
.doc-intro a, .doc-section a { text-decoration: underline; text-decoration-color: var(--muted); text-underline-offset: 0.14em; }
/* wide: three 25% fields on the 0/25/50/75 lines; the right field breathes.
   The lead sentence ends on the 50% line so it too sits on the grid. */
@media (min-width: 1200px) {
    .doc-grid { grid-template-columns: repeat(3, 25%); }
    .doc-intro { max-width: 50%; }
}
@media (max-width: 640px) {
    /* the doc is always taller than a phone, so top-align it and restore the gap
       below the "Index" nav link (matches the breathing room on the pager pages) */
    .page--doc .page-body { align-self: start; padding-top: calc(var(--rhythm) * 2); }
    .doc-grid { grid-template-columns: 1fr; }
    .doc-section { padding-right: 0; }
    .doc-intro { max-width: none; }
}
/* true 4K: the doc heading grows too — placed after the base .doc-title so it wins on source order (continuous at 2800: 1.71vw ≈ 3rem) */
@media (min-width: 2800px) { .doc-title { font-size: clamp(3rem, 1.71vw, 4.5rem); } }

/* ── Global legal link (index + contact) — quiet chrome on the bottom frame,
      absolutely positioned so it never disturbs the centered composition ── */
.page { position: relative; }
.legal-link {
    position: absolute;
    left: calc(75vw - 0.5 * var(--pad));   /* left edge on the 75% grid line (4th column), like the rest */
    bottom: calc(var(--pad) + env(safe-area-inset-bottom, 0px));
    z-index: 3;
    color: var(--muted);
    font-size: clamp(0.8125rem, 0.4rem + 0.36vw, 1.25rem);  /* same scale as the site-head chrome — Privacy Policy matches Contact information directly above it */
    text-transform: uppercase;
    letter-spacing: 0.06em;
    transition: color 0.3s var(--ease);
}
.legal-link:hover { color: var(--fg); }

/* ── Mobile overrides that must follow the base rules above (source order) ── */
@media (max-width: 640px) {
    /* newsletter spans the full column on phones — the desktop 25% grid cap is too narrow */
    .newsletter { width: auto; min-width: 0; max-width: none; }
    /* On phones, Privacy Policy sits at the bottom-left (in the grid, row 4),
       where the nav link used to be — the nav has moved up under the title */
    .legal-link {
        position: static;
        grid-row: 4;
        grid-column: 1;
        justify-self: start;
        font-size: 0.875rem;
        text-decoration: underline;
        text-decoration-thickness: 1px;
        text-underline-offset: 0.25em;
        text-decoration-color: var(--muted);
    }
}

