/* travisyr.com — one stylesheet. Colors and fonts from the Figma frame 289:2. */

:root {
    --cream: #fff3e6;
    --red: #c53d3d;
    --ink: #000;
    --main: var(--cream);
}

@font-face {
    font-family: "Racing Sans One";
    src: url("/_/fonts/RacingSansOne/RacingSansOne-Regular.ttf") format("truetype");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

* { box-sizing: border-box; }

html { background: var(--cream); }

body {
    margin: 0;
    font-family: Georgia, "Times New Roman", serif;
    font-size: 17px;
    line-height: 1.55;
    color: var(--ink);
    background: var(--cream);
}

a { color: var(--red); }

/* ── Hero header ───────────────────────────────────────────────────────
   The Figma frame: a 1677×938 picture card with a 30px radius and a 1px
   black border, a cream inset curving down over its top that holds the
   nav, the shield hanging from the inset, and the title riding the top
   edge. Everything inside is sized in cqw against the card's width, so it
   scales as one piece. */

/* The card keeps 5vh above and below it at every window size. Its height
   is fixed at 90vh; its width follows the Figma ratio until the window is
   too narrow, then it takes the width and the picture crops to cover. */
.hero {
    position: relative;
    padding: 5vh 24px 0;
}

/* Smoke from the cigarette (smoke.js), over the picture and the title,
   rising off the top of the page. */
.smoke {
    position: absolute;
    left: 0;
    top: 0;
    z-index: 5;
    pointer-events: none;
}

.hero__card {
    container-type: inline-size;
    position: relative;
    height: 90vh;
    width: min(calc(90vh * 1677 / 938), 100%);
    margin: 0 auto;
    border-radius: 30px;
    /* About 5px on a 1440-wide Mac window, scaling with the card. */
    --rim: 0.36cqw;
}

/* The cutout. The Figma inset shape is cut out of the top of the card,
   so the page flows down into the picture. Its box in card units: 1253
   wide at 0.05958cqw a unit (74.66cqw), starting 1.55cqw above the top. */

/* The rim: Argent silver, painted by ui/_/code/metal.js. The gradient is
   what shows without WebGL2. The card's shape is cut from it. */
.hero__card > .metal {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    border-radius: inherit;
    background: linear-gradient(135deg, #ffffff 0%, #dfe3e8 15%, #a6acb5 35%, #8b8f95 50%, #b4bac2 64%, #eef1f4 82%, #ffffff 100%);
    -webkit-mask: linear-gradient(#000 0 0), url("/_/images/cut.svg") center -1.55cqw / 74.66cqw 6.49cqw no-repeat;
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0), url("/_/images/cut.svg") center -1.55cqw / 74.66cqw 6.49cqw no-repeat;
    mask-composite: exclude;
}

/* The photo sits over the metal, inset by the rim, and the same cutout
   grown by the rim is cut from it, so a band of silver runs along the
   curve as well as the edges. cut_grown.svg is padded 20 units a side,
   so its box is 77.04cqw by 8.88cqw and starts 1.19cqw higher; the photo
   box itself starts one rim lower than the card. */
.hero__photo {
    position: absolute;
    inset: var(--rim);
    border-radius: calc(30px - var(--rim));
    background: var(--cream);
    overflow: hidden;
    container-type: size;
    -webkit-mask: linear-gradient(#000 0 0), url("/_/images/cut_grown.svg") center calc(-2.74cqw - var(--rim)) / 77.04cqw 8.88cqw no-repeat;
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0), url("/_/images/cut_grown.svg") center calc(-2.74cqw - var(--rim)) / 77.04cqw 8.88cqw no-repeat;
    mask-composite: exclude;
}

/* Inner pages: a shorter band of the photo. The width stays the home
   page's, because the shield, title, nav, and rim are all sized from the
   card's width; only the height changes, so nothing in the header moves
   between pages. */
.hero--page .hero__card {
    height: 34vh;
}
.hero--page .hero__photo { --focus-y: 28%; }

/* The layered picture, sized like background-size: cover inside the photo
   box, and anchored at --focus-y (centre on home, higher on inner pages). */
.hero__scene {
    position: absolute;
    left: 50%;
    top: var(--focus-y, 50%);
    width: max(100cqw, calc(100cqh * 1536 / 864));
    aspect-ratio: 1536 / 864;
    translate: -50% calc(-1 * var(--focus-y, 50%));
}
.hero__sky,
.hero__land {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
}
/* A cloud layer is a strip that tiles sideways with no seam: its last 160
   columns are blended into its first, so it repeats every 1376 of the
   picture's 1536 columns. It drifts forever; sky.js moves it. */
.hero__clouds {
    position: absolute;
    left: 0;
    width: 100%;
    background-repeat: repeat-x;
    background-size: calc(100% * 1376 / 1536) 100%;
    will-change: background-position;
}

/* The title is Figma's outlined text (fill plus outside stroke), as an
   SVG: 918x22 at x 412, y -3 of the 1677-wide card. */
.hero__title {
    position: absolute;
    left: 24.57cqw;
    top: -0.18cqw;
    width: 54.74cqw;
    margin: 0;
    line-height: 0;
    z-index: 3;
}
.hero__title a { display: block; }
.hero__title img { display: block; width: 100%; height: auto; }

/* The nav row: 35px below the card top, each link at its Figma x. All
   measured against the card (1677 = 100cqw). */
.hero__nav {
    position: absolute;
    left: 0;
    top: 2.09cqw;
    width: 100%;
    height: 1.5cqw;
    z-index: 2;
}

.hero__link {
    position: absolute;
    top: 0;
    font-family: "Racing Sans One", Impact, sans-serif;
    font-size: 1.19cqw;
    line-height: 1;
    color: var(--ink);
    text-decoration: none;
    white-space: nowrap;
}
.hero__link:nth-child(1) { left: 28.4cqw; }
.hero__link:nth-child(2) { left: 37.9cqw; }
.hero__link:nth-child(3) { left: 56.2cqw; }
.hero__link:nth-child(4) { left: 65.9cqw; }

.hero__link:hover,
.hero__link.is-current { color: var(--red); text-decoration: underline; text-underline-offset: 3px; }

/* The shield hangs from the inset: 104×149 at x 765, y 32. The red piece
   is a separate layer in Figma, a square turned 45°, centred at (52, 101)
   of the shield. */
.hero__shield {
    position: absolute;
    left: 45.6cqw;
    top: 1.9cqw;
    width: 6.22cqw;
    height: 8.9cqw;
    z-index: 2;
}
.hero__shield-body { display: block; width: 100%; height: 100%; }
.hero__shield-red {
    position: absolute;
    left: 49.7%;
    top: 67.9%;
    width: 61.2%;
    aspect-ratio: 1;
    height: auto;
    transform: translate(-50%, -50%) rotate(-45deg);
}

/* Small nav, shown only when the inset is too small to read. */
.hero__nav--small {
    display: none;
    justify-content: center;
    gap: 1.4em;
    margin: 14px 0 0;
    font-family: "Racing Sans One", Impact, sans-serif;
    font-size: 18px;
}
.hero__nav--small a { color: var(--ink); text-decoration: none; }
.hero__nav--small a:hover,
.hero__nav--small a.is-current { color: var(--red); text-decoration: underline; }

@media (max-width: 720px) {
    .hero { padding-top: 48px; }
    .hero__nav { display: none; }
    .hero__card > .metal, .hero__photo { -webkit-mask: none; mask: none; }
    .hero__card { border-radius: 18px; height: auto; width: 100%; aspect-ratio: 4 / 3; }
    .hero__card { --rim: 4px; }
    .hero__photo { border-radius: calc(18px - var(--rim)); }
    .hero--page .hero__card { height: auto; aspect-ratio: 3 / 1; }
    /* The title sits above the card, in the padding, in up to three lines. */
    .hero__title {
        left: 0;
        top: auto;
        bottom: 100%;
        width: 100%;
        margin-bottom: 14px;
    }
    .hero__nav--small { display: flex; }
}

/* ── Page body ──────────────────────────────────────────────────────── */

.page {
    max-width: 1100px;
    margin: 0 auto;
    padding: 56px 24px 80px;
}

h1 {
    font-family: "Racing Sans One", Impact, sans-serif;
    font-weight: normal;
    font-size: 2.4rem;
    letter-spacing: 0.02em;
    margin: 0 0 0.6em;
    text-align: center;
}

h2 {
    font-family: "Racing Sans One", Impact, sans-serif;
    font-weight: normal;
    font-size: 1.4rem;
    margin: 0 0 0.3em;
}

.about {
    max-width: 44em;
    margin: 0 auto;
    font-size: 1.15rem;
    text-align: justify;
}
.about .lead {
    font-family: "Racing Sans One", Impact, sans-serif;
    font-size: 1.35em;
    color: var(--red);
}
.about .cta { text-align: center; margin-top: 2.5em; }

.content { max-width: 52em; margin: 0 auto; }
.content--narrow { max-width: 34em; }

.button {
    display: inline-block;
    padding: 0.6em 1.4em;
    margin: 0 0.4em;
    font-family: "Racing Sans One", Impact, sans-serif;
    font-size: 1.05rem;
    letter-spacing: 0.03em;
    color: var(--cream);
    background: var(--red);
    border: 1px solid var(--ink);
    border-radius: 999px;
    text-decoration: none;
    cursor: pointer;
}
.button:hover { background: #a92f2f; }
.button--plain { color: var(--ink); background: transparent; }
.button--plain:hover { background: rgba(0, 0, 0, 0.06); }

/* Events */
.events { list-style: none; padding: 0; margin: 2em 0 0; }
.event {
    display: flex;
    gap: 1.5em;
    padding: 1.2em 0;
    border-top: 1px solid var(--ink);
}
.event:last-child { border-bottom: 1px solid var(--ink); }
.event__date {
    flex: 0 0 6em;
    font-family: "Racing Sans One", Impact, sans-serif;
    font-size: 1.3rem;
    color: var(--red);
}
.event__body p { margin: 0; }

/* Forms, after comalyr: outlined fields, a spring on focus. */
.form { display: flex; flex-direction: column; margin-top: 1.5em; }
.form label { margin: 1em 0 0.3em; font-weight: bold; }
.form .required { color: var(--red); }
.form input:not([type="submit"]):not([type="hidden"]),
.form textarea {
    padding: 0.5em 0.6em;
    font: inherit;
    color: var(--ink);
    background: var(--cream);
    border: none;
    outline: 1px solid var(--ink);
    outline-offset: 0;
    border-radius: 0;
}
.form input:focus,
.form textarea:focus {
    animation: field-spring 360ms cubic-bezier(.2, .75, .25, 1) forwards;
}
@keyframes field-spring {
    0% { outline-offset: 0; }
    52% { outline-offset: 7px; }
    74% { outline-offset: 2px; }
    100% { outline-offset: 4px; }
}
.form .button { align-self: center; margin-top: 2em; }

/* The honeypot. Off screen, not display:none, so bots still see it. */
.trap {
    position: absolute;
    left: -10000px;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.footer {
    padding: 2em 24px 3em;
    text-align: center;
    font-size: 0.9rem;
    color: #444;
}
.footer p { margin: 0.3em 0; }
.footer a { color: inherit; }

/* Single-page navigation moves focus to <main>; it needs no outline. */
main.page:focus { outline: none; }


/* ── Opening animation (intro.js) ──────────────────────────────────────
   html.intro is set before the first paint. Only the shield shows; the
   frame and photo are clipped to a zero-width line at the centre, and the
   words and page are hidden. intro.js plays the sequence, then removes the
   class, which leaves everything in its normal state. */
html.intro .hero__shield,
html.intro .hero__title,
html.intro .hero__nav,
html.intro .hero__nav--small,
html.intro main.page,
html.intro .footer,
html.intro canvas.smoke {
    opacity: 0;
}
html.intro .hero__card > .metal,
html.intro .hero__photo {
    clip-path: inset(0 50% 0 50%);
}

/* The silver lines that draw down from the shield and open the frame. They
   share the metal's cutout mask, so their tops follow the curve. */
.hero__intro {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    -webkit-mask: linear-gradient(#000 0 0), url("/_/images/cut.svg") center -1.55cqw / 74.66cqw 6.49cqw no-repeat;
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0), url("/_/images/cut.svg") center -1.55cqw / 74.66cqw 6.49cqw no-repeat;
    mask-composite: exclude;
}
.hero__intro-bar {
    position: absolute;
    width: max(var(--rim), 3px);
    background: linear-gradient(180deg, #ffffff 0%, #dfe3e8 18%, #a6acb5 38%, #8b8f95 50%, #b4bac2 62%, #eef1f4 82%, #ffffff 100%);
    /* A dark hairline so the silver reads on cream, and a soft shine. */
    box-shadow: 0 0 0 0.5px rgba(0, 0, 0, 0.35), 0 0 8px rgba(255, 255, 255, 0.9);
    border-radius: 999px;
}
