/* ===================================
   MICHAEL'S CREATIVE PORTFOLIO
   Cartoon rolodex theme
   ===================================

   The look: flat colour, thick ink outlines, hard offset shadows, paper
   tabs. Everything on the page is a card or a sticker, so it reads on any
   of the backgrounds the rolodex moves between.

   --ground is the page background. main.js rewrites it as the rolodex
   settles on each card; the value here is the ground for the first card,
   so there is no flash of a different colour before the script runs.

   Animation policy, carried over from the binder site: only transform
   and opacity animate, with two deliberate exceptions (the rail tabs'
   width and the ghost card's box), both on small elements with nothing
   inside that could reflow.
   =================================== */

:root {
    --ground: #cf284d;
    --ink: #15111c;
    --paper: #fff7e8;
    --paper-bright: #fffdf8;
    --metal: #d9dde6;

    --font-display: 'Lilita One', 'Arial Rounded MT Bold', 'Trebuchet MS', sans-serif;
    --font-body: 'Nunito', 'Segoe UI', system-ui, -apple-system, sans-serif;

    --line: 3px;
    --line-thick: 4px;
    --shadow: 5px 5px 0 var(--ink);
    --shadow-small: 3px 3px 0 var(--ink);
    --shadow-big: 9px 9px 0 var(--ink);

    --ease-out: cubic-bezier(0.22, 0.61, 0.36, 1);
    --ease-pop: cubic-bezier(0.2, 0.9, 0.25, 1.25);

    --edge: clamp(12px, 3vw, 32px);
}

/* ===================================
   RESET & BASE
   =================================== */

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

html {
    background: var(--ground);
    -webkit-text-size-adjust: 100%;
}

body {
    min-height: 100vh;
    background: var(--ground);
    color: var(--ink);
    font-family: var(--font-body);
    font-size: 16px;
    line-height: 1.6;
    overflow-x: hidden;
}

/* With the app running the rolodex is the page; cards scroll inside
   themselves. */
html.js body {
    height: 100vh;
    height: 100dvh;
    overflow: hidden;
}

img,
video,
iframe {
    max-width: 100%;
}

button {
    font: inherit;
    color: inherit;
}

a {
    color: inherit;
}

:focus-visible {
    outline: var(--line) solid var(--ink);
    outline-offset: 3px;
    box-shadow: 0 0 0 calc(var(--line) + 3px) var(--paper);
}

.visually-hidden {
    position: absolute !important;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.skip-link {
    position: fixed;
    left: -9999px;
    top: 12px;
    z-index: 100;
    padding: 10px 16px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 12px;
    font-weight: 800;
    text-decoration: none;
}

.skip-link:focus {
    left: 12px;
}

/* ===================================
   STAGE
   =================================== */

.stage {
    position: fixed;
    inset: 0;
    z-index: 0;
    /* Swipes turn the drum; the browser must not scroll or zoom instead. */
    touch-action: none;
}

.stage-canvas {
    display: block;
    width: 100%;
    height: 100%;
    opacity: 0;
    transition: opacity 700ms ease;
    -webkit-tap-highlight-color: transparent;
}

.has-rolodex .stage-canvas {
    opacity: 1;
}

/* While three.js downloads: three little cards taking turns to flip. */
.stage-loader {
    position: absolute;
    left: 50%;
    top: 50%;
    display: flex;
    gap: 10px;
    transform: translate(-50%, -50%);
    perspective: 400px;
}

.stage-loader span {
    width: 34px;
    height: 46px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 7px;
    box-shadow: var(--shadow-small);
    transform-origin: 50% 100%;
    animation: loader-flip 1.2s var(--ease-out) infinite;
}

.stage-loader span:nth-child(2) { animation-delay: 150ms; }
.stage-loader span:nth-child(3) { animation-delay: 300ms; }

@keyframes loader-flip {
    0%, 55%, 100% { transform: rotateX(0deg); }
    30% { transform: rotateX(-75deg); }
}

.has-rolodex .stage-loader,
.no-rolodex .stage-loader,
html:not(.js) .stage {
    display: none;
}

/* ===================================
   STICKERS OVER THE STAGE
   =================================== */

.stage-ui {
    position: relative;
    z-index: 10;
    transition: opacity 240ms ease;
}

/* An open card has the screen to itself. */
.panel-open .stage-ui {
    opacity: 0;
    pointer-events: none;
}

html:not(.js) .stage-ui > :not(.tab-rail) {
    display: none;
}

.brand {
    position: fixed;
    top: var(--edge);
    left: var(--edge);
    z-index: 10;
    display: inline-flex;
    flex-direction: column;
    padding: 9px 18px 11px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 16px;
    box-shadow: var(--shadow);
    text-decoration: none;
    transform: rotate(-2.5deg);
    transition: transform 260ms var(--ease-pop), box-shadow 260ms var(--ease-out);
}

.brand:hover {
    transform: rotate(-1deg) translate(-2px, -2px);
    box-shadow: 7px 7px 0 var(--ink);
}

.brand:active {
    transform: rotate(-2.5deg) translate(3px, 3px);
    box-shadow: 2px 2px 0 var(--ink);
}

.brand__name {
    font-family: var(--font-display);
    font-size: clamp(1.1rem, 2.1vw, 1.55rem);
    line-height: 1;
    letter-spacing: 0.01em;
}

.brand__sub {
    margin-top: 5px;
    font-size: 0.7rem;
    font-weight: 900;
    letter-spacing: 0.2em;
    text-transform: uppercase;
}

/* The index tabs, on the right edge. Each peeks out in its card's colour
   and slides open to show its label; the card on show keeps its tab
   open. */
.tab-rail {
    position: fixed;
    top: 50%;
    right: 0;
    z-index: 10;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    transform: translateY(-50%);
}

.rail-tab {
    display: flex;
    align-items: center;
    width: 34px;
    height: 46px;
    padding-left: 15px;
    overflow: hidden;
    background: var(--card);
    border: var(--line) solid var(--ink);
    border-right: 0;
    border-radius: 14px 0 0 14px;
    box-shadow: 0 4px 0 var(--ink);
    text-decoration: none;
    transition: width 420ms cubic-bezier(0.22, 0.68, 0.24, 1);
}

.rail-tab:hover,
.rail-tab:focus-visible,
.rail-tab[aria-current] {
    width: 112px;
}

.rail-tab:focus-visible {
    outline-offset: -8px;
    box-shadow: 0 4px 0 var(--ink);
}

.rail-label {
    font-family: var(--font-display);
    font-size: 1.05rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transform: translateX(10px);
    transition: opacity 280ms ease 90ms, transform 380ms cubic-bezier(0.22, 0.68, 0.24, 1) 60ms;
}

.rail-tab:hover .rail-label,
.rail-tab:focus-visible .rail-label,
.rail-tab[aria-current] .rail-label {
    opacity: 1;
    transform: none;
}

/* What the rolodex is showing, and the way in. */
.now-card {
    position: fixed;
    left: 50%;
    bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px));
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 7px 7px 7px 12px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 999px;
    box-shadow: var(--shadow);
    transform: translateX(-50%);
}

.now-card__swatch {
    width: 24px;
    height: 24px;
    flex: none;
    background: var(--card, var(--paper));
    border: var(--line) solid var(--ink);
    border-radius: 7px;
    transform: rotate(-8deg);
}

.now-card__label {
    min-width: 6.2ch;
    font-family: var(--font-display);
    font-size: 1.3rem;
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.now-card__open {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px 10px 18px;
    background: var(--ink);
    color: var(--paper);
    border: 0;
    border-radius: 999px;
    font-weight: 900;
    font-size: 0.95rem;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: transform 220ms var(--ease-pop);
}

.now-card__open svg {
    width: 16px;
    height: 16px;
    fill: none;
    stroke: currentColor;
    stroke-width: 3;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.now-card__open:hover {
    transform: scale(1.06) rotate(-2deg);
}

.now-card__open:active {
    transform: scale(0.96);
}

.stage-hint {
    position: fixed;
    left: 50%;
    bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px) + 72px);
    z-index: 10;
    max-width: calc(100vw - 24px);
    padding: 6px 14px;
    background: rgba(21, 17, 28, 0.62);
    color: var(--paper);
    border-radius: 999px;
    font-size: 0.84rem;
    font-weight: 800;
    text-align: center;
    transform: translateX(-50%);
    transition: opacity 600ms ease, transform 600ms var(--ease-out);
    pointer-events: none;
}

.hint-dismissed .stage-hint,
.no-rolodex .stage-hint {
    opacity: 0;
    transform: translate(-50%, 10px);
}

.hint-touch {
    display: none;
}

@media (hover: none) {
    .hint-pointer { display: none; }
    .hint-touch { display: inline; }
}

/* ===================================
   CARDS (SECTIONS)
   Without scripting they are a stack of big cards down the page. With the
   app running they are hidden until one is opened, and then it is fixed
   in the middle of the screen with its body scrolling.
   =================================== */

.sections {
    max-width: 1120px;
    margin: 0 auto;
    padding: 110px 16px 64px;
    display: grid;
    gap: 70px;
}

html.js .sections {
    padding: 0;
}

.section-card {
    position: relative;
    display: flex;
    flex-direction: column;
    margin-top: 40px;
    background: var(--card);
    border: var(--line-thick) solid var(--ink);
    border-radius: 26px;
    box-shadow: var(--shadow-big);
    color: var(--ink);
}

html.js .section-card {
    display: none;
    margin: 0;
}

html.js .section-card.is-open,
html.js .section-card.is-measuring {
    display: flex;
    position: fixed;
    z-index: 50;
    top: clamp(52px, 8vh, 84px);
    right: clamp(10px, 4vw, 60px);
    bottom: clamp(12px, 4vh, 40px);
    left: clamp(10px, 4vw, 60px);
    max-width: 1120px;
    margin: 0 auto;
}

html.js .section-card.is-measuring {
    visibility: hidden;
}

html.js .section-card.is-open {
    animation: card-land 260ms var(--ease-out);
}

@keyframes card-land {
    from { box-shadow: 3px 3px 0 var(--ink); }
    to { box-shadow: var(--shadow-big); }
}

/* Paper texture: faint index-card ruling. */
.section-card::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: repeating-linear-gradient(to bottom, transparent 0 38px, rgba(21, 17, 28, 0.08) 38px 40px);
}

.section-card__header {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 16px;
    padding: 18px 18px 16px clamp(18px, 3vw, 36px);
    border-bottom: var(--line) solid var(--ink);
}

.section-card__tab {
    position: absolute;
    left: clamp(22px, 5%, 60px);
    bottom: calc(100% + var(--line-thick) - 2px);
    padding: 7px 22px 5px;
    background: var(--paper);
    border: var(--line-thick) solid var(--ink);
    border-bottom: 0;
    border-radius: 14px 14px 0 0;
    font-family: var(--font-display);
    font-size: 1.15rem;
    line-height: 1.1;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.section-card__titles {
    min-width: 0;
}

.section-card h2 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.9rem, 5vw, 3.3rem);
    line-height: 1.02;
    letter-spacing: 0.01em;
    color: var(--paper);
    -webkit-text-stroke: 7px var(--ink);
    paint-order: stroke fill;
    text-shadow: 4px 4px 0 var(--ink);
}

.section-tagline {
    margin-top: 8px;
    font-size: clamp(0.98rem, 2vw, 1.15rem);
    font-weight: 800;
    font-style: italic;
}

.section-card__close {
    flex: none;
    display: grid;
    place-items: center;
    width: 48px;
    height: 48px;
    margin-left: auto;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 50%;
    box-shadow: var(--shadow-small);
    cursor: pointer;
    transition: transform 240ms var(--ease-pop), box-shadow 160ms ease;
}

.section-card__close svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: var(--ink);
    stroke-width: 3.6;
    stroke-linecap: round;
}

.section-card__close:hover {
    transform: rotate(90deg) scale(1.06);
}

.section-card__close:active {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--ink);
}

.section-card__body {
    position: relative;
    flex: 1;
    min-height: 0;
    padding: clamp(16px, 3vw, 36px);
}

html.js .section-card__body {
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: var(--ink) transparent;
}

/* The content pops in just after the ghost card lands. */
html.js .section-card.is-open .section-card__body > * {
    animation: content-in 420ms var(--ease-out) both;
}

html.js .section-card.is-open .section-card__body > :nth-child(2) {
    animation-delay: 70ms;
}

@keyframes content-in {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
}

.section-card__flip {
    position: relative;
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 10px clamp(14px, 3vw, 30px) 12px;
    border-top: var(--line) solid var(--ink);
}

html:not(.js) .section-card__close,
html:not(.js) .section-card__flip {
    display: none;
}

.flip-button {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 999px;
    box-shadow: var(--shadow-small);
    font-weight: 900;
    font-size: 0.92rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    cursor: pointer;
    transition: transform 200ms var(--ease-pop), box-shadow 150ms ease;
}

.flip-button:hover {
    transform: translate(-2px, -2px);
    box-shadow: 5px 5px 0 var(--ink);
}

.flip-button:active {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--ink);
}

/* ===================================
   PANEL LAYER: scrim and ghost
   =================================== */

.panel-layer {
    position: fixed;
    inset: 0;
    z-index: 40;
}

.panel-scrim {
    position: absolute;
    inset: 0;
    background: rgba(21, 17, 28, 0.42);
    opacity: 0;
    transition: opacity 320ms ease;
}

.panel-layer.is-visible .panel-scrim {
    opacity: 1;
}

.panel-ghost {
    position: fixed;
    background: var(--card);
    border: var(--line-thick) solid var(--ink);
    border-radius: 12px;
    box-shadow: var(--shadow-big);
    pointer-events: none;
}

/* The card's title rides along, so it reads as the same card growing. */
.panel-ghost__title {
    position: absolute;
    left: 50%;
    top: 50%;
    font-family: var(--font-display);
    font-size: clamp(2rem, 6vw, 4rem);
    line-height: 1;
    white-space: nowrap;
    color: var(--paper);
    -webkit-text-stroke: 8px var(--ink);
    paint-order: stroke fill;
    text-shadow: 5px 5px 0 var(--ink);
    transform: translate(-50%, -50%) rotate(-3deg);
}

.panel-ghost::before {
    content: attr(data-label);
    position: absolute;
    left: 7%;
    bottom: 100%;
    padding: 5px 18px 3px;
    background: var(--paper);
    border: var(--line-thick) solid var(--ink);
    border-bottom: 0;
    border-radius: 12px 12px 0 0;
    font-family: var(--font-display);
    font-size: 1rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
}

/* ===================================
   SHARED CONTENT PIECES
   =================================== */

.content-grid {
    display: grid;
    gap: clamp(16px, 2.6vw, 30px);
    min-width: 0;
}

.content-card,
.card-info,
.project-media {
    min-width: 0;
}

.content-card {
    background: var(--paper-bright);
    border: var(--line) solid var(--ink);
    border-radius: 20px;
    box-shadow: var(--shadow);
    padding: clamp(14px, 2vw, 22px);
    transition: transform 260ms var(--ease-pop), box-shadow 260ms var(--ease-out);
}

@media (hover: hover) and (pointer: fine) {
    .content-card:hover {
        transform: translate(-3px, -3px) rotate(-0.4deg);
        box-shadow: 8px 8px 0 var(--ink);
    }
}

.card-info h3 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.45rem, 3vw, 1.9rem);
    line-height: 1.1;
    letter-spacing: 0.01em;
    margin-bottom: 6px;
}

.content-card p {
    line-height: 1.6;
}

.card-subtitle,
.project-tagline {
    font-weight: 800;
    font-style: italic;
    margin-bottom: 6px;
}

.card-tags {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 14px;
}

.tag {
    padding: 2px 11px;
    background: var(--card);
    border: 2px solid var(--ink);
    border-radius: 999px;
    font-size: 0.74rem;
    font-weight: 900;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.card-link,
.social-link {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    margin-top: 16px;
    padding: 10px 18px;
    background: var(--ink);
    color: var(--paper);
    border: var(--line) solid var(--ink);
    border-radius: 999px;
    box-shadow: 4px 4px 0 rgba(21, 17, 28, 0.35);
    font-weight: 900;
    text-decoration: none;
    transition: transform 220ms var(--ease-pop), box-shadow 220ms ease, background-color 160ms ease, color 160ms ease;
}

.card-link svg,
.social-link svg {
    width: 18px;
    height: 18px;
    flex: none;
}

.card-link svg {
    fill: none;
    stroke: currentColor;
    stroke-width: 2.4;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.card-link:hover,
.social-link:hover {
    background: var(--paper);
    color: var(--ink);
    transform: translate(-2px, -2px) rotate(-1deg);
    box-shadow: 6px 6px 0 var(--ink);
}

.card-link:active,
.social-link:active {
    transform: translate(2px, 2px);
    box-shadow: 1px 1px 0 var(--ink);
}

.external-links {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    margin-top: 10px;
}

.social-link.instagram:hover { color: #c1245a; }
.social-link.youtube:hover { color: #d10000; }
.social-link.etsy:hover { color: #d85500; }

/* ===================================
   CONTENTS (the start card)
   =================================== */

.contents {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 230px), 1fr));
    gap: 34px 20px;
    padding-top: 22px;
}

.contents__item {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 120px;
    padding: 16px 18px 18px;
    background: var(--card);
    border: var(--line) solid var(--ink);
    border-radius: 0 16px 16px 16px;
    box-shadow: var(--shadow);
    text-decoration: none;
    transition: transform 240ms var(--ease-pop), box-shadow 240ms var(--ease-out);
}

.contents__item:hover {
    transform: translate(-3px, -3px) rotate(-1deg);
    box-shadow: 8px 8px 0 var(--ink);
}

.contents__item:active {
    transform: translate(2px, 2px);
    box-shadow: 2px 2px 0 var(--ink);
}

.contents__tab {
    position: absolute;
    left: -3px;
    bottom: calc(100% - 1px);
    padding: 3px 14px 1px;
    background: var(--paper);
    border: var(--line) solid var(--ink);
    border-bottom: 0;
    border-radius: 10px 10px 0 0;
    font-family: var(--font-display);
    font-size: 0.9rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.contents__heading {
    font-family: var(--font-display);
    font-size: 1.45rem;
    line-height: 1.1;
}

.contents__tagline {
    font-weight: 700;
    font-style: italic;
    line-height: 1.35;
}

/* ===================================
   PROJECT CARDS (games + software)
   =================================== */

.games-grid,
.software-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
    align-items: start;
}

.project-card {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.project-media {
    position: relative;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--ink);
    border: var(--line) solid var(--ink);
    border-radius: 14px;
}

.project-media > video,
.project-media > picture,
.project-media img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: top center;
    transition: transform 400ms var(--ease-out);
}

.project-card:hover .project-media img {
    transform: scale(1.04);
}

/* Cota's rota screen is a tall page; show the top of it rather than a crop
   through the middle of the grid. */
.project-card[data-accent="cota"] .project-media {
    aspect-ratio: 4 / 3;
}

.project-thumbs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.thumb {
    flex: 1 1 0;
    min-width: 72px;
    max-width: 140px;
    aspect-ratio: 16 / 9;
    padding: 0;
    overflow: hidden;
    background: var(--ink);
    border: var(--line) solid var(--ink);
    border-radius: 10px;
    cursor: pointer;
    opacity: 0.78;
    transition: opacity 150ms ease, transform 220ms var(--ease-pop), box-shadow 150ms ease;
}

.thumb img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.thumb:hover,
.thumb:focus-visible {
    opacity: 1;
    transform: translateY(-2px) rotate(-1.5deg);
}

.thumb.active {
    opacity: 1;
    box-shadow: 0 0 0 3px var(--card), 0 0 0 6px var(--ink);
}

/* ===================================
   MOKA
   =================================== */

.moka-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 320px), 1fr));
}

.moka-grid .content-card {
    display: flex;
    flex-direction: column;
}

.moka-grid .card-preview {
    margin-bottom: 14px;
}

.moka-grid .app-screenshot {
    display: block;
    width: 100%;
    height: auto;
    border: var(--line) solid var(--ink);
    border-radius: 14px;
}

.moka-grid .card-info {
    display: flex;
    flex-direction: column;
    flex-grow: 1;
}

.moka-grid .card-link {
    align-self: flex-start;
    margin-top: auto;
}

.moka-grid .card-tags {
    margin-bottom: 16px;
}

/* ===================================
   WRITING — BOOKS
   =================================== */

.writing-grid {
    display: flex;
    flex-direction: column;
    gap: clamp(20px, 3vw, 32px);
}

.book-hint {
    margin-bottom: 14px;
    text-align: center;
    font-weight: 800;
    font-style: italic;
}

.book-covers {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(18px, 3vw, 34px);
}

.book-card.interactive-book {
    position: relative;
    width: clamp(140px, 40vw, 180px);
    aspect-ratio: 2 / 3;
    overflow: hidden;
    background: #000;
    border: var(--line) solid var(--ink);
    border-radius: 10px;
    box-shadow: var(--shadow);
    cursor: pointer;
    transition: transform 260ms var(--ease-pop), box-shadow 260ms var(--ease-out);
}

.book-card.interactive-book:nth-child(1) { transform: rotate(-3deg); }
.book-card.interactive-book:nth-child(3) { transform: rotate(3deg); }

.book-card.interactive-book:hover,
.book-card.interactive-book.open {
    transform: translateY(-8px) rotate(0deg);
    box-shadow: 9px 12px 0 var(--ink);
}

.book-card .book-cover-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 350ms ease;
}

.book-card.open .book-cover-img {
    opacity: 0;
}

.book-content {
    position: absolute;
    inset: 0;
    z-index: 10;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 0.8rem;
    text-align: center;
    opacity: 0;
    visibility: hidden;
    transition: opacity 350ms ease, visibility 350ms ease;
}

.book-card.open .book-content {
    opacity: 1;
    visibility: visible;
}

.book-page {
    position: absolute;
    inset: 0.8rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    opacity: 0;
    pointer-events: none;
    transform: translateX(8px);
    transition: opacity 300ms ease, transform 300ms var(--ease-out);
}

.book-page.active {
    opacity: 1;
    pointer-events: auto;
    transform: translateX(0);
}

.book-page p,
.book-page li {
    margin-bottom: 0.5rem;
    font-family: 'Times New Roman', Times, serif;
    font-size: clamp(0.7rem, 1.9vw, 0.82rem);
    line-height: 1.3;
    color: inherit;
}

.book-emphasis {
    margin-top: 0.75rem;
    font-weight: bold;
}

.book-soon {
    font-weight: 600;
    letter-spacing: 0.05em;
}

.book-page ul.clean-list {
    list-style: none;
    text-align: left;
}

.book-page ul.clean-list li {
    position: relative;
    margin-bottom: 0.25rem;
    padding-left: 0.8rem;
}

.book-page ul.clean-list li::before {
    content: "•";
    position: absolute;
    left: 0;
}

.book-progress {
    position: absolute;
    left: 0;
    bottom: 0;
    z-index: 12;
    width: 0;
    height: 4px;
    background: currentColor;
    opacity: 0;
    transition: width 300ms var(--ease-out), opacity 300ms ease;
}

.book-card.open .book-progress {
    opacity: 0.6;
}

.ooster-promo {
    display: flex;
    align-items: center;
    gap: clamp(16px, 3vw, 32px);
    padding: clamp(14px, 2.4vw, 26px);
    background: var(--paper-bright);
    border: var(--line) solid var(--ink);
    border-radius: 20px;
    box-shadow: var(--shadow);
}

.ooster-promo picture {
    flex: 0 0 auto;
}

.promo-image {
    display: block;
    width: clamp(120px, 24vw, 240px);
    height: auto;
    border: var(--line) solid var(--ink);
    border-radius: 14px;
    transform: rotate(-2deg);
}

.promo-text h3 {
    margin-bottom: 6px;
    font-family: var(--font-display);
    font-weight: 400;
    font-size: clamp(1.4rem, 3vw, 1.9rem);
    line-height: 1.1;
}

.promo-text p {
    font-weight: 700;
}

/* ===================================
   OOSTER INLINE MAILING FORM
   =================================== */

.ooster-inline-form {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 100%;
    max-width: 320px;
    min-width: min(200px, 100%);
    height: 50px;
    margin-top: 14px;
    padding: 8px 16px;
    overflow: hidden;
    background: var(--card);
    border: var(--line) solid var(--ink);
    border-radius: 999px;
    box-shadow: var(--shadow-small);
    cursor: pointer;
    transition: transform 200ms var(--ease-pop), background-color 250ms ease;
}

.ooster-inline-form:not(.active):not(.success):hover {
    transform: translate(-2px, -2px);
}

.ooster-inline-form.active {
    padding: 4px 10px 4px 18px;
    background: var(--paper-bright);
    cursor: default;
}

.ooster-inline-form.success {
    justify-content: center;
    background: #6fdc8c;
    cursor: default;
    pointer-events: none;
}

.input-wrapper {
    position: relative;
    flex: 1;
    display: flex;
    align-items: center;
    height: 100%;
    min-width: 0;
    margin-right: 8px;
}

.btn-text {
    position: absolute;
    left: 0;
    width: 100%;
    white-space: nowrap;
    font-weight: 900;
    font-size: 0.98rem;
    transition: opacity 250ms ease;
}

.ooster-inline-form.active .btn-text,
.ooster-inline-form.success .btn-text {
    opacity: 0;
    pointer-events: none;
}

.email-input {
    width: 100%;
    min-width: 0;
    background: transparent;
    border: none;
    outline: none;
    color: var(--ink);
    font-family: var(--font-body);
    font-weight: 700;
    font-size: 16px; /* 16px stops iOS zooming the page on focus */
    opacity: 0;
    pointer-events: none;
    transition: opacity 250ms ease;
}

.ooster-inline-form.active .email-input {
    opacity: 1;
    pointer-events: auto;
}

.envelope-btn {
    position: relative;
    z-index: 10;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
}

.emoji-icon {
    position: absolute;
    top: 50%;
    left: 50%;
    font-size: 20px;
    line-height: 1;
    opacity: 0;
    pointer-events: none;
    transform: translate(-50%, -50%) scale(0.5);
    transition: opacity 250ms ease, transform 250ms var(--ease-out);
}

.icon-default {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

.ooster-inline-form.active .icon-default {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
}

.ooster-inline-form.active .icon-active,
.ooster-inline-form.success .icon-success {
    opacity: 1;
    transform: translate(-50%, -50%) scale(1);
}

.ooster-inline-form.success .icon-default,
.ooster-inline-form.success .icon-active {
    opacity: 0;
    transform: translate(-50%, -50%) scale(0.5);
}

.success-message {
    position: absolute;
    font-weight: 900;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity 250ms ease, transform 250ms var(--ease-out);
}

.ooster-inline-form.success .success-message {
    opacity: 1;
    transform: translateY(0);
}

/* ===================================
   ART
   =================================== */

.art-grid {
    grid-template-columns: 1fr;
}

.art-showcase {
    display: flex;
    flex-direction: column;
    gap: clamp(18px, 3vw, 30px);
}

.art-collage {
    overflow: hidden;
    border: var(--line-thick) solid var(--ink);
    border-radius: 20px;
    box-shadow: var(--shadow);
}

.collage-image {
    display: block;
    width: 100%;
    height: auto;
    transition: transform 400ms var(--ease-out);
}

.art-collage:hover .collage-image {
    transform: scale(1.02);
}

.paintjammer-brand {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: clamp(14px, 2.4vw, 22px);
    background: var(--paper-bright);
    border: var(--line) solid var(--ink);
    border-radius: 20px;
    box-shadow: var(--shadow);
}

.brand-icon {
    flex-shrink: 0;
    width: 62px;
    height: 62px;
    border: var(--line) solid var(--ink);
    border-radius: 14px;
}

.paintjammer-brand h3 {
    font-family: var(--font-display);
    font-weight: 400;
    font-size: 1.6rem;
    line-height: 1.1;
}

.paintjammer-brand p {
    font-weight: 700;
}

/* ===================================
   PHOTOGRAPHY
   =================================== */

.photo-grid {
    grid-template-columns: 1fr;
}

.photo-gallery {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: clamp(12px, 2.4vw, 26px);
}

.photo-item {
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--ink);
    border: var(--line) solid var(--ink);
    border-radius: 16px;
    box-shadow: var(--shadow);
    transition: transform 260ms var(--ease-pop);
}

.photo-item:nth-child(odd) { transform: rotate(-1deg); }
.photo-item:nth-child(even) { transform: rotate(1deg); }

.photo-item:hover {
    transform: rotate(0deg) scale(1.02);
}

.photo-img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ===================================
   VIDEOGRAPHY
   =================================== */

.video-grid {
    grid-template-columns: 1fr;
}

.video-embed-container {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--ink);
    border: var(--line-thick) solid var(--ink);
    border-radius: 20px;
    box-shadow: var(--shadow);
}

.video-embed-container iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: none;
}

/* ===================================
   FLAT MODE (no WebGL)
   The tab rail becomes a big index in the middle of the screen.
   =================================== */

.no-rolodex .tab-rail {
    top: 50%;
    right: auto;
    left: 50%;
    display: grid;
    grid-template-columns: repeat(2, minmax(130px, 210px));
    gap: 16px;
    transform: translate(-50%, -50%);
}

.no-rolodex .rail-tab,
.no-rolodex .rail-tab:hover,
.no-rolodex .rail-tab[aria-current] {
    width: auto;
    height: 62px;
    padding: 0 18px;
    border-right: var(--line) solid var(--ink);
    border-radius: 16px;
    box-shadow: var(--shadow);
}

.no-rolodex .rail-label {
    opacity: 1;
    transform: none;
    font-size: 1.3rem;
}

.no-rolodex .now-card {
    display: none;
}

/* Without scripting, the rail is a plain row of links at the top. */
html:not(.js) .tab-rail {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: stretch;
    padding: 24px 12px 0;
    transform: none;
}

html:not(.js) .rail-tab {
    width: auto;
    height: 44px;
    padding: 0 14px;
    border-right: var(--line) solid var(--ink);
    border-radius: 12px;
}

html:not(.js) .rail-label {
    opacity: 1;
    transform: none;
}

html:not(.js) .sections {
    padding-top: 40px;
}

/* ===================================
   RESPONSIVE
   =================================== */

@media (max-width: 760px) {
    .brand {
        padding: 7px 13px 9px;
        border-radius: 13px;
    }

    .tab-rail {
        gap: 5px;
    }

    .rail-tab,
    .rail-tab:hover,
    .rail-tab:focus-visible {
        width: 24px;
        height: 36px;
        padding-left: 0;
        border-radius: 10px 0 0 10px;
    }

    /* No room for labels on a phone; the now-showing sticker names the
       card instead, and the open tab just sticks out further. */
    .rail-tab[aria-current] {
        width: 36px;
    }

    .rail-label {
        display: none;
    }

    .now-card__label {
        font-size: 1.1rem;
    }

    .stage-hint {
        font-size: 0.76rem;
        bottom: calc(var(--edge) + env(safe-area-inset-bottom, 0px) + 66px);
    }

    html.js .section-card.is-open,
    html.js .section-card.is-measuring {
        top: 50px;
        right: 8px;
        bottom: 10px;
        left: 8px;
        border-radius: 20px;
    }

    .section-card__header {
        padding: 14px 12px 12px 16px;
    }

    .section-card__close {
        width: 42px;
        height: 42px;
    }

    .section-card h2 {
        -webkit-text-stroke-width: 5px;
        text-shadow: 3px 3px 0 var(--ink);
    }

    .games-grid,
    .software-grid,
    .moka-grid {
        grid-template-columns: 1fr;
    }

    .project-thumbs .thumb {
        max-width: none;
    }

    /* Three covers cannot sit side by side on a phone; a snapping shelf
       keeps them one swipe apart at a readable size. */
    .book-covers {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        padding: 10px 6px 16px;
        scrollbar-width: none;
    }

    .book-covers::-webkit-scrollbar {
        display: none;
    }

    .book-card.interactive-book {
        flex: 0 0 auto;
        width: 150px;
        scroll-snap-align: center;
    }

    .ooster-promo {
        flex-direction: column;
        align-items: flex-start;
    }

    .promo-image {
        width: min(220px, 60%);
    }

    .no-rolodex .tab-rail {
        grid-template-columns: repeat(2, minmax(120px, 1fr));
        width: calc(100vw - 32px);
    }

    .no-rolodex .rail-tab,
    .no-rolodex .rail-tab:hover,
    .no-rolodex .rail-tab[aria-current] {
        height: 54px;
    }

    .no-rolodex .rail-label {
        display: inline;
    }
}

@media (max-width: 480px) {
    .photo-gallery {
        gap: 10px;
    }

    .external-links {
        flex-direction: column;
    }

    .social-link {
        justify-content: center;
    }

    .paintjammer-brand {
        flex-direction: column;
        text-align: center;
    }

    .flip-button {
        padding: 7px 12px;
        font-size: 0.82rem;
    }
}

@media (max-height: 560px) {
    .tab-rail {
        gap: 4px;
    }

    .rail-tab {
        height: 32px;
    }

    .stage-hint {
        display: none;
    }
}

/* Touch devices: no hover lifts. */
@media (hover: none), (pointer: coarse) {
    .content-card:hover,
    .contents__item:hover,
    .card-link:hover,
    .social-link:hover,
    .flip-button:hover,
    .brand:hover {
        transform: none;
    }

    .brand:hover {
        transform: rotate(-2.5deg);
    }

    .photo-item:hover,
    .art-collage:hover .collage-image,
    .project-card:hover .project-media img {
        transform: none;
    }

    .book-card.interactive-book:hover {
        transform: none;
    }
}

/* ===================================
   REDUCED MOTION
   =================================== */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

    html.js .section-card.is-open .section-card__body > * {
        animation: none;
    }
}
