/* Self-hosted Young Serif -- Google Fonts only serves a single static
   400 weight (which reads fairly heavy/bold on its own, with no lighter
   cut to fall back to), but the typeface's own source repo
   (github.com/noirblancrouge/YoungSerif, OFL-licensed, same license
   Google Fonts uses) ships proper variable-weight builds with a real
   light-to-bold range plus genuine italics (not browser-synthesized
   oblique). font-weight below picks a point on that range per element --
   see body's and .nav-link's own font-weight for the values chosen. */
@font-face {
    font-family: "Young Serif";
    src: url("fonts/Young-Serif-wght.woff2") format("woff2-variations"),
         url("fonts/Young-Serif-wght.woff2") format("woff2");
    font-weight: 100 900;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "Young Serif";
    src: url("fonts/Young-Serif-Italic-wght.woff2") format("woff2-variations"),
         url("fonts/Young-Serif-Italic-wght.woff2") format("woff2");
    font-weight: 100 900;
    font-style: italic;
    font-display: swap;
}

/* Adjust this to change how wide the hero title/tagline (and the nav
   links/page content below, which share it) can grow. 480px reads as a
   deliberate column on a typical desktop — noticeably wider than before,
   still clearly narrower than the page. Below that width, every use of
   this pairs it with calc(100vw - 48px) rather than a vw fraction, so
   narrowing the window doesn't shrink the content proportionally smaller
   and smaller — it just keeps the same fixed 24px margin body itself
   uses (padding: 60px 24px, below), the way a phone browser would. */
:root {
    --hero-max-width: 480px;
}

:root {
    --bg: #130918;

    --white:  #dddddd;
    --yellow: #e6c36d;
    --green:  #91c48d;
    --blue:   #82bdf4;
    --purple: #c0a7ea;
    --pink:   #d99ab4;
    --gray:   #8d9198;
    --marionberry: #b6678f;

    /* The nav/Q&A buttons' face once pressed (see .nav-button.answered
       and .links-item .nav-button.page-title) — a dimmed --yellow, light
       enough to still read clearly as "yellow, just muted" rather than
       going all the way to a muddy brown. */
    --yellow-pressed: #c6a85e;
}

/* Spacing scale — four named gaps, each a clean multiple of the 26px body
   font. Fixed px (not em) so a value means the same thing everywhere it's
   used, regardless of the font-size of whichever element it's applied to.
   Some locations below need a slightly different raw value to *produce*
   one of these visible gaps once combined with a neighboring padding or a
   flex-centered box — those are commented with which tier they're for. */
:root {
    --space-lockup:  6.5px;  /* elements presented as one joined unit (hero title + tagline) */
    --space-snug:    4px;    /* a closely related block follows -- tightened so a header visibly "belongs" to its own text, not the section above it */
    --space-rhythm:  13px;   /* the default beat — paragraph to paragraph, item to item; deliberately less than one line's height, so it reads as a paragraph break, not a bigger gap */
    --space-section: 36px;   /* a hard break between functionally different parts */
}

html {
    background: var(--bg);
    /* .hero and .links-bleed both intentionally bleed to 100vw to escape
       body's centered max-width column -- on iOS Safari specifically,
       100vw can compute a few px wider than the actual visible viewport
       (it reserves space for a scrollbar that doesn't really exist on
       mobile), which otherwise leaves the page just barely
       horizontally scrollable/rubber-bandable. Clipping overflow here is
       the standard fix, without having to touch the bleed technique
       itself (a max-width: 100% swap wouldn't work -- these elements
       need to escape body's own max-width, not be capped by it). */
    overflow-x: hidden;
}

body {
    overflow-x: hidden;
}

/* Hidden until web fonts finish loading (see script.js), so we never flash
   fallback-font text before swapping to VT323. */
body {
    visibility: hidden;
}

body.fonts-loaded {
    visibility: visible;
}

body {
    margin: 0 auto;
    max-width: 760px;

    padding: 32px 24px 60px;

    /* No background here on purpose -- html's own (identical) background
       shows through fine, and this way body's box never has an opaque
       fill that could interfere with anything positioned behind it. */
    color: var(--white);

    font-family: "Young Serif", serif;
    font-weight: 420; /* bumped up a bit from 380 -- trying the "a little more bold" direction first; ask to go the other way (lighter, e.g. ~340) to compare */
    font-size: 20px;
    line-height: 1.3;
}

p {
    margin: 0 0 var(--space-rhythm) 0;
}

a {
    color: var(--blue);
    text-decoration: underline;
}

.white  { color: var(--white); }
.yellow { color: var(--yellow); }
.green  { color: var(--green); }
.blue   { color: var(--blue); }
.purple { color: var(--purple); }
.pink   { color: var(--pink); }
.gray   { color: var(--gray); }

.indent {
    margin-left: 2em;
}

/* Berry rain (side margins) — berries drift down outside the centered
   text column (script.js computes that rectangle, padded out a bit, and
   only ever spawns berries entirely to its left or right), so they
   never cross the text at all here, regardless of how tall the column
   grows. Naturally produces few or no berries on narrow screens, where
   there's little/no margin left on either side -- .below-berry-rain
   (below) is what carries the rain there instead. pointer-events:none
   keeps it from blocking clicks even where a berry visually overlaps
   something. See script.js for the tunable count/size/speed/opacity
   constants. */
.berry-rain {
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}

/* Berry rain (below the revealed content) — always spans the full page
   height and the text column's own width (left/width set in script.js,
   matching .berry-rain's avoided rectangle), but a dynamically-updated
   clip-path (also script.js -- see updateBelowBerryRainGeometry) hides
   everything from the top down to wherever the currently-revealed
   content currently ends. As more text/buttons appear, that boundary
   moves down and the visible strip below it shrinks accordingly --
   berries already below it keep falling completely undisturbed, and any
   that are now above it simply stop being painted, which reads as "the
   new text's background covered it" without actually needing to track
   individual letters. */
.below-berry-rain {
    position: fixed;
    top: 0;
    bottom: 0;
    overflow: hidden;
    pointer-events: none;
}

.berry {
    position: absolute;
    top: -10vh;
    animation-name: berry-fall;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}

@keyframes berry-fall {
    from { transform: translateY(0)     rotate(0deg); }
    to   { transform: translateY(120vh) rotate(360deg); }
}

/* Hero — bleeds out of the centered column to span the full viewport width */

.hero {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
    /* Fixed px (not em) -- these are the values 0.2em/0.6em used to compute
       back when body's font-size was 26px. Left as literal px so this
       stays put regardless of body's font-size (now Young Serif/16px). */
    padding: 5.2px 0 15.6px;
}

/* Both lines are fit (via JS) to exactly this box's width, so their edges
   always align regardless of font or character count. */
.hero-box {
    width: min(calc(100vw - 48px), var(--hero-max-width));
    margin: 0 auto;
    text-align: center;
}

.hero-title {
    width: fit-content; /* shrink-to-fit, so JS can measure true text width */
    margin: 0 auto;
    font-family: "VT323", monospace;
    font-weight: normal;
    font-size: 10vw; /* fallback until JS fits it exactly to the hero-box width */
    line-height: 0.7;
    white-space: nowrap;
    color: #ffffff;
}

/* VT323 is monospace (fixed advance width per character), but its narrow
   glyphs (i, o, .) leave a lot of visual whitespace in their cell — these
   pull specific letters in the title closer to fix the resulting uneven
   gaps. Each gap gets its own class so they can be tuned independently.
   Values are in em so they scale with the title's dynamic font-size. */
.kern-mario-i {
    margin-left: -0.08em; /* gap before the i in "mario" (closer to the r) */
}

.kern-mario-o {
    margin-left: -0.08em; /* gap before the o in "mario" (closer to the i) */
}

.kern-dot {
    margin-left: -0.15em; /* gap before the . (closer to the y) */
}

.kern-final-i {
    margin-left: -0.13em; /* gap before the final i (closer to the .) */
}

.kern-final-o {
    margin-left: -0.08em; /* gap before the final o (closer to the i) */
}

.hero-tagline {
    width: fit-content; /* shrink-to-fit, so JS can measure true text width */
    margin: 0.3em auto 0;
    font-family: "VT323", monospace; /* decoupled from body's font-family (Young Serif) -- stays pixel-font like .hero-title, which sets this explicitly too */
    font-style: italic;
    font-size: 3vw; /* fallback until JS fits it exactly to the hero-box width */
    white-space: nowrap;
    color: var(--marionberry);
}

/* Nav links — the site's other pages, linked from the home page */

/* Bleeds out to the viewport the same way .hero does, so the inner .links
   box below can be aligned to the exact same left/right edges as .hero-box. */
.links-bleed {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}

/* Same width and centering as .hero-box, so links stay within that box.
   21.85px margin-top here, plus .hero's own 15.6px padding-bottom, plus
   .links-item's own 14.55px padding-top = a --space-section (52px) gap
   from the tagline down to WHAT IS THIS (or the heading, once
   transformed) — this value on its own isn't one of the four tiers, it's
   what's needed to produce one once combined with those paddings. */
.links {
    width: min(calc(100vw - 48px), var(--hero-max-width));
    margin: 21.85px auto 0;
}

/* 14.55px (not --space-snug's 13px) — originally tuned so two adjacent
   .links-item paddings landed the WHAT IS THIS <-> CONTACT gap on exactly
   --space-rhythm back when there were two nav buttons; CONTACT's gone
   now, but this value is still load-bearing for the tagline gap above
   (see .links) and the heading -> content gap below (see .links-item + p
   / .verify-box), so it stays as-is. */
.links-item {
    padding: 14.55px 0;
    line-height: 1.4;
    text-align: center; /* centers the WHAT IS THIS button (and, once settled, the plain-text title it becomes) — doesn't affect the body copy typed in below, since that lives in sibling <p>s, not inside this element */
}

.nav-link {
    background: none;
    border: none;
    margin: 0;
    padding: 0;

    font-family: inherit; /* picks up body's Young Serif */
    font-weight: 700; /* bold end of the variable range -- doesn't inherit body's lighter 380, buttons/titles stay the bolder look */
    color: #d9c084;
    font-style: italic;
    font-size: 25px; /* fixed (not em) so it doesn't ride on body's font-size -- see .page-title below, which matches this */
    text-decoration: none;
    cursor: pointer;
}

.nav-link:hover,
.nav-link:focus-visible {
    text-decoration: underline;
}

/* WHAT IS THIS (and the fade-in Q&A buttons typed inline into it — see
   .qa-button-row/typeBlocks below) get an old-school pressable-brick look: a
   flat yellow face with a hard (unblurred) bevel and a solid drop edge on
   the bottom-right, like the button is physically sitting above the page.
   Hover nudges it slightly toward the page (a light depress, shadow drop
   shrinking to match); clicking pushes it the rest of the way down flush,
   inverting the bevel to read as fully "pressed in." No border-radius or
   blur anywhere, to stay in the same hard-pixel register as the VT323
   font and the berries. */
/* .nav-button itself is the click/hover/focus target and never moves or
   resizes -- it just wraps .nav-button-face (below) tightly, so its own
   hit box always matches the face's *resting* footprint. Only
   transform-origin still matters here, for the JS-driven fall-in
   animation (dropButtonIntoPlace), which animates this outer element
   directly (that's a one-off, pointer-events:none while it's happening,
   unrelated to hover/press below). */
.nav-button {
    display: inline-block;
    margin: 0 0 3.4px 0;
    transform-origin: center bottom;
}

/* The actual visible "brick" -- background, padding, bevel, and the text
   itself all live here, on a child span, not on .nav-button. This is
   what physically moves on hover/press (see :hover/:active below): since
   .nav-button-face is painted on top of its stationary parent button and
   pointer/click hit-testing always follows what's actually rendered
   (bubbling straight back up to .nav-button either way, whether the
   cursor lands on the face itself or, in the sliver the face just moved
   out of, directly on the parent underneath it), the click target never
   walks out from under a stationary cursor the way it did when the
   whole .nav-button used to move. */
.nav-button-face {
    display: inline-block;
    /* Left/right padding isn't quite symmetric -- Young Serif italic's
       ink still sits slightly left-inset and right-overhanging relative
       to its own advance-width box (measured via canvas
       actualBoundingBox*, ~0.9-2px of rightward bias across the
       actual button labels at this weight/size). Shifting ~1.25px from
       the left side to the right compensates. */
    padding: 0.15em calc(0.55em + 1.25px) 0.15em calc(0.55em - 1.25px);
    background: var(--yellow);
    color: var(--bg);
    font-style: italic;
    text-decoration: none;
    /* Young Serif's variable weight axis actually clamps at 700 (checked
       via canvas ink-density sampling -- 750-900 all render pixel-
       identical to 700), so font-weight can't push this any bolder on
       its own. A thin stroke in the same color as the fill fattens the
       strokes a bit further without the distortion browser-synthesized
       bold would cause. currentColor keeps it in sync with whichever
       text color is active (this dark fill, or --yellow once settled --
       see .nav-button.answered/.page-title .nav-button-face below,
       which doesn't need to repeat this). */
    -webkit-text-stroke: 0.4px currentColor;
    box-shadow:
        inset 2px 2px 0 0 #f8e9c4,
        inset -2px -2px 0 0 #8a6a2f,
        4px 4px 0 0 #5c4520;
    /* transform stays fast/separate from the rest -- snappy hover/press
       feel, distinct from the 0.2s box-shadow/background-color/color/
       padding group, which is also what plays when .answered/.page-title
       lands (see below), melting the whole brick into plain text. */
    transition: transform 0.08s ease-out, box-shadow 0.2s ease-out, background-color 0.2s ease, color 0.2s ease, padding 0.2s ease;
}

.nav-button:hover .nav-button-face,
.nav-button:focus-visible .nav-button-face {
    background: #eecf85;
    transform: translate(1px, 1px);
    box-shadow:
        inset 2px 2px 0 0 #f8e9c4,
        inset -2px -2px 0 0 #8a6a2f,
        3px 3px 0 0 #5c4520;
}

.nav-button:active .nav-button-face {
    transform: translate(3px, 3px);
    box-shadow:
        inset -2px -2px 0 0 #f8e9c4,
        inset 2px 2px 0 0 #8a6a2f;
}

/* The <p> wrapping each fade-in Q&A button (see waitForFallingButtonClick
   in script.js) — centered like .links-item above (same reasoning: only
   the button/question, never the answer prose, which lives in sibling
   <p>s). margin-bottom is --space-snug, matching the heading -> content
   gap below (the question "owns" its answer, so it should read snug).
   margin-top is --space-section instead of the ordinary paragraph-to-
   paragraph --space-rhythm -- this is a new question/section starting,
   not just the next paragraph, so it gets the same hard-break treatment
   as any other section boundary. Margins collapse against the preceding
   paragraph's own margin-bottom (the browser takes the larger of the
   two), so this alone determines the gap regardless of --space-rhythm. */
.qa-button-row {
    margin-top: var(--space-section);
    margin-bottom: var(--space-snug);
    text-align: center;
}

/* Once clicked — both the fade-in Q&A buttons (.nav-button.answered) and
   WHAT IS THIS / CONTACT itself (.links-item .nav-button.page-title) —
   the brick look melts away entirely into plain colored text: no face,
   no padding, no bevel, just --yellow text where the label already was.
   Since the button/heading's container is centered (see .links-item /
   .qa-button-row above) and this padding is removed symmetrically, the
   text's own center point never moves — only the box around it shrinks
   away. Selector list combines both cases since the end state is now
   identical either way; .links-item .nav-button.page-title still needs
   that specific scoping (not just .nav-button.page-title) so it reliably
   wins over .page-title / .links-item .page-title's generic heading look
   (same specificity as some of those, and .page-title comes later in the
   file) — .nav-button.answered has no such competing rule to beat. */
.nav-button.answered,
.links-item .nav-button.page-title {
    display: inline-block;
    margin: 0 0 3.4px 0;
    cursor: text; /* no longer a button once settled, just text -- the ordinary selection cursor reads more honestly than the arrow */
    /* <button> text is unselectable by default (browsers special-case
       "auto" to behave like "none" on form controls, even though it
       still computes as "auto") -- explicitly forcing "text" here is
       what actually lets double-click/drag select this like normal
       prose now that it no longer acts like a button. */
    user-select: text;
    -webkit-user-select: text;
}

/* transform here matches .nav-button:active .nav-button-face exactly --
   the settled title sits precisely where the brick was at the moment it
   was fully pressed, so there's no jump as it melts from "pressed brick"
   into plain text right on release. */
.nav-button.answered .nav-button-face,
.links-item .nav-button.page-title .nav-button-face {
    padding: 0;
    background: none;
    color: var(--yellow);
    font-style: italic;
    text-decoration: none;
    box-shadow: none;
    transform: translate(3px, 3px);
}

/* Page content — body copy on the non-home pages, aligned to the same
   column width as the hero box and nav links above. */
.page-content {
    width: min(calc(100vw - 48px), var(--hero-max-width));
    margin: 0.5em auto 0;
}

/* Matches body's 1.3 -- Young Serif reads better with roomier spacing
   than the tighter 1.1 this was set to back when the reveal text was VT323. */
#content p {
    line-height: 1.3;
}

/* The first paragraph right after a transformed heading (WHAT IS THIS's
   text) — sits closer to its heading than paragraph-to-paragraph spacing
   (the heading "owns" this content, so it reads as a closely related
   block rather than a peer paragraph — see --space-snug), matching the
   same --space-snug gap .qa-button-row below uses after each fade-in
   Q&A button. .links-item's own 14.55px padding-bottom already opens
   more space than that target on its own, and the heading itself is a
   .nav-button (padding + border, not just plain text) which measured out
   to 3.4px taller than the old plain-.nav-link heading this value was
   originally tuned against — same correction as .nav-button's own
   margin-bottom (see its comment). Net effect: this pulls back hard
   enough to net out at --space-snug (13px) rather than the padding and
   the two just stacking. */
.links-item + p {
    margin-top: -13.94px;
}

/* When a nav-link button turns into the page title in place (see
   script.js), it stays inside its original .links-item row — that row's
   own padding already provides the spacing, so skip the standalone
   .page-title margin here to avoid doubling up. */
.links-item .page-title {
    margin: 0;
}

.page-title {
    display: block;
    margin: 0 0 0.75em 0;
    color: #d9c084;
    font-size: 25px; /* fixed -- matches .nav-link, so the title reads the same size before and after the button is pressed */
    font-style: italic;
    text-decoration: underline;
    cursor: text; /* matches .nav-button.answered/.links-item .nav-button.page-title -- settled titles are just text, not buttons */
    user-select: text;
    -webkit-user-select: text;
}

/* Holds the Turnstile widget, then later the revealed email — a fixed
   slot (see script.js) so replacing one with the other never shifts
   anything below it. min-height matches Turnstile's standard widget
   height, so the box is already that tall before the widget even loads,
   and the shorter email line that eventually replaces it is centered
   (both axes — vertically within the box via align-items, horizontally
   via justify-content, matching the centered button/title above it)
   rather than sitting at its top-left. This always follows the last
   typed <p> of WHAT IS THIS's flow, whose own 32.5px margin-bottom wins
   the margin collapse against this margin-top outright — comfortably
   bigger than the negative value here (kept the same as .links-item + p
   above, for the no-longer-reachable case of this instead directly
   following a heading — harmless either way, so not worth a separate
   value just for that).
   margin-bottom is --space-snug rather than the default paragraph
   --space-rhythm — this is the last thing on the page, so that trailing
   space just reads as a gap before the page ends, not a beat between two
   peer paragraphs. */
.verify-box {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 65px;
    margin: -13.94px 0 var(--space-snug) 0;
}

/* The default <p> bottom margin would count toward flex centering and
   bias the visible content upward within the box — strip it here. */
.verify-box p {
    margin: 0;
}

.turnstile-holder {
    margin: 0;
}

.email-link {
    font-family: "VT323", monospace; /* matches the hero title/tagline, decoupled from the surrounding Young Serif prose */
    /* VT323's x-height runs about 25% shorter than Young Serif's at the
       same px (measured via canvas text metrics) -- 20px would read as
       the same visual size as the 16px Young Serif body copy around it;
       bumped a bit past that on request, to stand out a little more. */
    font-size: 28px;
    color: var(--white);
    text-decoration: none;
}

.email-link:hover,
.email-link:focus-visible {
    text-decoration: underline;
}

.copy-btn {
    display: inline-flex;
    align-items: center;
    position: relative;
    top: 0.08em;
    background: none;
    border: none;
    margin: 0 0 0 6px; /* gap to the email text -- fixed px, not em, so it stays put regardless of this button's own font-size */
    padding: 0;

    font-family: inherit; /* buttons don't inherit page font-size by default either */
    /* This button's own font-size no longer directly sets the icon's
       pixel size -- both COPY_ICON_SVG and COPIED_ICON_SVG (script.js)
       carry their own explicit font-size now, since they needed
       different sizing logic. Kept here mainly for the `top: 0.08em`
       nudge above. */
    font-size: 15.68px;
    color: var(--marionberry);
    cursor: pointer;

    /* Establishes the 3D context .copy-btn-icon's flip (see flipCopyIcon
       in script.js) rotates within, so it reads as a card tilting back
       in space rather than just a flat horizontal squish. */
    perspective: 200px;
}

/* The part that actually spins in flipCopyIcon -- kept separate from
   .copy-btn itself so the button's own box (aria/title, click target)
   never has a transform on it, only this inner face does. */
.copy-btn-icon {
    display: inline-flex;
    align-items: center;
}
