/* The landing page for erwindegroot.nl.

   The palette is deliberately the one both apps already use - dark chrome, a single warm
   yellow accent - so arriving here and then opening either app feels like one place rather
   than three. The values come from the PhotoSpiralysis site (--bg #101216, --accent
   #ffe000) and from Fractalysis' app.css, which reach for the same yellow from opposite
   directions; #ffe000 is the one that holds up as text on a dark ground, so it wins. */
:root {
    --bg: #101216;
    --bg-card: rgba(24, 27, 33, 0.72);
    --bg-card-hover: rgba(32, 36, 44, 0.86);
    --border: rgba(255, 255, 255, 0.09);
    --border-hover: rgba(255, 224, 0, 0.45);
    --text: #e8eaed;
    --text-dim: #9aa0ac;
    --accent: #ffe000;
    color-scheme: dark;
}

* {
    box-sizing: border-box;
}

/* Text for screen readers and nothing else. Clipped to a single pixel rather than hidden
   with display:none or visibility:hidden, both of which take it out of the accessibility
   tree along with the layout - which would defeat the entire point. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

html,
body {
    margin: 0;
    min-height: 100%;
}

body {
    /* Two soft pools of colour, one per app, sitting where the cards sit. They are the
       whole background if the canvas never starts, and they stay underneath it when it
       does - the canvas is drawn with a low alpha and lets these through. */
    background:
        radial-gradient(60rem 40rem at 12% 18%, rgba(255, 60, 140, 0.12), transparent 60%),
        radial-gradient(55rem 38rem at 88% 78%, rgba(0, 150, 255, 0.12), transparent 60%),
        var(--bg);
    color: var(--text);
    font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    -webkit-font-smoothing: antialiased;
    display: flex;
    flex-direction: column;
    min-height: 100dvh;
}

#backdrop {
    position: fixed;
    inset: 0;
    z-index: -1;
    width: 100%;
    height: 100%;
    /* Barely there. Enough that the page is not static, far too faint to compete with the
       card artwork, which is the thing that is meant to be looked at. */
    opacity: 0.32;
    pointer-events: none;
}

main {
    width: 100%;
    max-width: 64rem;
    margin: 0 auto;
    padding: clamp(2.5rem, 8vh, 6rem) 1.5rem 2rem;
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: clamp(2rem, 6vh, 3.5rem);
}

/* --- masthead --------------------------------------------------------------------- */

.masthead {
    text-align: center;
}

.masthead h1 {
    margin: 0;
    /* The heading is now a whole domain on one unbreakable line, so it has to be sized to
       fit rather than left to wrap. 8.5vw is the rate at which it still clears the page
       padding on a 320px screen - the narrowest phone worth caring about - and it is a
       steeper ramp than the old 6vw, so on an ordinary 375px phone the name comes out
       slightly larger than it was before the domain was added, not smaller. */
    font-size: clamp(1.6rem, 8.5vw, 3.25rem);
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.1;
}

/* "www." and ".nl" - the domain around the name. Smaller, lighter and dimmer, so the eye
   reads the name first and the address second, from one line of type. Sitting on the same
   baseline is what keeps it looking like an address rather than a logo with superscripts. */
.host-affix {
    font-size: 0.4em;
    font-weight: 500;
    letter-spacing: 0;
    color: var(--text-dim);
}

/* Margins rather than typed spaces: a space here would be a place the line could break. */
.host-affix-lead {
    margin-right: 0.45em;
}

.host-affix-trail {
    margin-left: 0.45em;
}

.tagline {
    margin: 0.85rem auto 0;
    max-width: 34rem;
    color: var(--text-dim);
    font-size: clamp(0.95rem, 1.6vw, 1.075rem);
    line-height: 1.55;
}

/* --- app cards -------------------------------------------------------------------- */

.apps {
    display: grid;
    /* min(19rem, 100%) rather than a bare 19rem: a plain minmax floor is a hard minimum,
       so on a screen narrower than 19rem plus the page padding the track refuses to shrink
       and the cards hang off the right edge. Capping the floor at the container's own width
       lets the single column shrink with the viewport instead. */
    grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
    gap: 1.5rem;
}

.app-card {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 1rem;
    overflow: hidden;
    /* The card is a link, so it is one element; its children are spans laid out as blocks
       rather than divs, because a div inside an <a> is legal but a span is what this
       actually is - inline content given a box. */
    backdrop-filter: blur(12px);
    transition: transform 220ms ease, border-color 220ms ease, background-color 220ms ease, box-shadow 220ms ease;
}

.app-card:hover,
.app-card:focus-visible {
    transform: translateY(-4px);
    background: var(--bg-card-hover);
    border-color: var(--border-hover);
    box-shadow: 0 1.25rem 2.5rem rgba(0, 0, 0, 0.45);
}

.app-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

/* 4:3, because that is the shape of both pictures. Neither is cropped by CSS: the
   PhotoSpiralysis photo is 4:3 as exported and has content it cannot lose at both edges -
   the bear's ears at the top, the watermark at the bottom - and the Fractalysis render was
   cropped to 4:3 when it was resized for the web. So object-fit never has a decision to
   make, at any card width. */
.app-art {
    display: block;
    position: relative;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: #07080a;
    /* A hairline between art and text, so the card still reads as two parts on a screen
       where the artwork happens to be dark at the bottom edge. */
    border-bottom: 1px solid var(--border);
}

/* There is deliberately no gradient scrim over the bottom of the artwork. One looked right
   over the generated pictures these cards used to carry, and wrong over real ones: it
   greys out the bright corner of the Fractalysis render and dims the watermark along the
   bottom of the PhotoSpiralysis photo. The hairline border above does the separating. */

.art-image {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 400ms ease;
}

.app-card:hover .art-image,
.app-card:focus-visible .art-image {
    transform: scale(1.04);
}

.app-body {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 1.35rem 1.4rem 1.5rem;
    flex: 1;
}

.app-name {
    font-size: 1.3rem;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.app-blurb {
    color: var(--text-dim);
    font-size: 0.95rem;
    line-height: 1.55;
    /* Pushes the call to action to the bottom, so the two cards line their "Open the app"
       rows up with each other even when one blurb runs a line longer. */
    flex: 1;
}

.app-go {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    margin-top: 0.35rem;
    color: var(--accent);
    font-size: 0.95rem;
    font-weight: 600;
}

.go-arrow {
    width: 1.05em;
    height: 1.05em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    transition: transform 220ms ease;
}

.app-card:hover .go-arrow,
.app-card:focus-visible .go-arrow {
    transform: translateX(0.25rem);
}

/* --- colophon --------------------------------------------------------------------- */

.colophon {
    margin-top: auto;
    padding-top: 1rem;
    text-align: center;
    color: var(--text-dim);
    font-size: 0.875rem;
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.6rem;
    flex-wrap: wrap;
}

.colophon a {
    color: var(--text-dim);
    text-decoration: none;
    border-bottom: 1px solid transparent;
    transition: color 180ms ease, border-color 180ms ease;
}

.colophon a:hover,
.colophon a:focus-visible {
    color: var(--accent);
    border-bottom-color: var(--accent);
}

.dot {
    opacity: 0.5;
}

/* --- motion ----------------------------------------------------------------------- */

/* The backdrop animation and the card lift both stop for anyone who has asked for less
   motion. site.js checks the same query before starting its animation loop. */
@media (prefers-reduced-motion: reduce) {
    #backdrop {
        display: none;
    }

    .app-card,
    .art-image,
    .go-arrow {
        transition: none;
    }

    .app-card:hover,
    .app-card:focus-visible {
        transform: none;
    }
}
