/* Copyright © 2026 Patrick Angle. All rights reserved. */

/* The component library, addressed by custom element name rather than by class.
 *
 * Nothing here needs JavaScript. The elements arrive in the markup with their authored children, and every rule below
 * is a plain tag or attribute selector, so a page renders complete and styled before `Main.js` has defined a single
 * element. The definitions in `assets/js/Elements/` add behavior on top of a page that already works. */

@layer tokens {
    :root {
        /* The calm end of the type: mixed case, light axes. Cards, entries, and anything inside them inherit it, and a
           section or masthead re-declares these on itself so its own headings sit at the display end. A heading never
           names a size — it takes whatever the box it sits in is set to. */
        --heading-font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem);
        --heading-axis-settings: "SCTR" 70, "JMBL" 185, "COUT" 125;
        --heading-letter-spacing: normal;
        --heading-line-height: 1.05;
        --heading-text-transform: none;
    }
}

@layer components {
    /* Page scaffolding */

    /* Named grid columns stand in for the wrapper element the design used to center its content, which keeps the
       markup one level shallower and lets a decorative band claim `full` without leaving the flow. */
    page-section,
    page-masthead,
    article-masthead,
    home-hero,
    product-hero {
        display: grid;
        grid-template-columns:
            [full-start] minmax(var(--gutter-inline-size), 1fr)
            [content-start] minmax(0, var(--content-inline-size))
            [content-end] minmax(var(--gutter-inline-size), 1fr)
            [full-end];
        row-gap: var(--stack-gap, 1.5rem);
    }

    :is(page-section, page-masthead, article-masthead, home-hero, product-hero) > * {
        grid-column: content;
    }

    /* Format Collage's Scatter and Jumble axes bite hard on capitals and barely move the lowercase, which is what the
       foundry's own specimens lean on — clean lowercase set against collaged caps. Everything that wants the torn look
       is therefore uppercase, and the card end of the scale deliberately stays mixed case as the counterpoint. */
    :is(page-section, page-masthead, article-masthead, home-hero, product-hero) {
        --heading-font-size: clamp(2rem, 1.3rem + 3.2vw, 4rem);
        --heading-axis-settings: "SCTR" 115, "JMBL" 225, "COUT" 145;
        --heading-line-height: 1;
        --heading-text-transform: uppercase;
    }

    :is(page-masthead, home-hero, product-hero) {
        --heading-font-size: clamp(2.75rem, 1.5rem + 7vw, 8rem);
        --heading-axis-settings: "SCTR" 105, "JMBL" 215, "COUT" 150;
        --heading-letter-spacing: -0.01em;
        --heading-line-height: 0.92;
    }

    :is(collage-block, timeline-entry, resume-entry, block-grid > content-stack) {
        --heading-font-size: clamp(1.5rem, 1.2rem + 1.4vw, 2.25rem);
        --heading-axis-settings: "SCTR" 70, "JMBL" 185, "COUT" 125;
        --heading-letter-spacing: normal;
        --heading-line-height: 1.05;
        --heading-text-transform: none;
    }

    :is(h1, h2, h3, h4) {
        font-size: var(--heading-font-size);
        font-variation-settings: var(--heading-axis-settings);
        letter-spacing: var(--heading-letter-spacing);
        line-height: var(--heading-line-height);
        max-inline-size: none;
        text-transform: var(--heading-text-transform);
        text-wrap: balance;
    }

    page-section {
        padding-block: var(--section-block-padding);
    }

    /* A section that recesses onto its own ground, for the link columns and the download call to action. */
    page-section[tone="ink"] {
        background-color: var(--ink-color);
        color: var(--paper-color);
    }

    /* The viewport-relative term sets the drop on a tall screen; the clearance is the floor that keeps the kicker out
       from under the header on a short or narrow one, where a fraction of the height is less than the pill itself. */
    page-masthead {
        padding-block: max(var(--header-clearance-block-size), clamp(9rem, 18vh, 13rem)) clamp(2rem, 5vw, 4rem);
    }

    /* The head of a support article, which clears the floating header the way a masthead does but keeps the section
       scale: an article's title is a sentence, and the display scale would give a long one five lines. */
    article-masthead {
        padding-block: max(var(--header-clearance-block-size), clamp(8rem, 16vh, 11rem)) clamp(0.5rem, 2vw, 1.25rem);
    }

    /* Arrangements */

    content-stack {
        display: flex;
        flex-direction: column;
        gap: var(--stack-gap, 1.5rem);
    }

    section-intro {
        display: flex;
        flex-direction: column;
        gap: 1rem;
    }

    content-split {
        align-items: start;
        display: grid;
        gap: clamp(2rem, 5vw, 4rem);
        grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
    }

    content-columns {
        display: grid;
        gap: clamp(2rem, 4vw, 3.5rem);
        grid-template-columns: repeat(auto-fit, minmax(min(17rem, 100%), 1fr));
    }

    block-grid {
        display: grid;
        gap: var(--grid-gap, 1.25rem);
        grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min-inline-size, 16rem), 100%), 1fr));
    }

    /* Type */

    page-headline {
        display: block;
    }

    page-headline :is(h1, h2) {
        display: flex;
        flex-direction: column;
    }

    heading-line {
        display: block;
    }

    /* Only the key nouns take color; the rest of the line stays paper. Which words those are is the author's
       emphasis, so the content marks them with `*…*` and the cascade decides what color each one lands on. */
    page-headline heading-line:nth-of-type(6n + 1) em {
        color: var(--color-yellow);
    }

    page-headline heading-line:nth-of-type(6n + 3) em {
        color: var(--color-teal);
    }

    page-headline heading-line:nth-of-type(6n + 5) em {
        color: var(--color-pink);
    }

    :is(page-masthead, product-hero) :is(h1, h2) em {
        color: var(--page-accent-color);
    }

    page-kicker {
        align-self: start;
        border-block-end: 2px solid currentColor;
        display: block;
        font-size: 0.75rem;
        inline-size: fit-content;
        justify-self: start;
        letter-spacing: 0.22em;
        padding-block-end: 0.2em;
        rotate: -3deg;
        text-transform: uppercase;
        transform-origin: 0 100%;
    }

    page-kicker[accent] {
        color: var(--page-accent-color);
    }

    page-lede {
        display: block;
        font-size: clamp(1.15rem, 1rem + 0.8vw, 1.5rem);
        line-height: 1.4;
        max-inline-size: 40ch;
    }

    page-prose {
        display: flex;
        flex-direction: column;
        gap: 1.1em;
    }

    page-prose a {
        color: var(--page-accent-color);
        text-decoration-color: color-mix(in srgb, var(--page-accent-color) 45%, transparent);
    }

    page-prose a:hover {
        text-decoration-color: currentColor;
    }

    page-footnote {
        color: var(--page-muted-text-color);
        display: block;
        font-size: 0.8rem;
        line-height: 1.4;
    }

    /* Collage blocks — a slab of flat color, tilted a hair off true, the way the specimen butts blocks together. */

    collage-block {
        background-color: var(--collage-block-color, var(--color-yellow));
        border-radius: var(--block-corner-radius);
        color: var(--collage-block-text-color, var(--ink-color));
        display: flex;
        flex-direction: column;
        gap: 0.85rem;
        padding: clamp(1.5rem, 3vw, 2.5rem);
        position: relative;
        rotate: var(--collage-block-rotation, 0deg);
        transition: rotate 260ms ease, translate 260ms ease;
    }

    collage-block[tone="ink"] {
        --collage-block-color: var(--ink-color);
        --collage-block-text-color: var(--paper-color);
    }

    collage-block[tone="ink"] :is(h2, h3, h4) {
        color: var(--dark-block-heading-color);
    }

    collage-block p {
        max-inline-size: none;
    }

    /* Hue and tilt come from the block's place in its grid rather than from the content file: the specimen's language
       is a run of butted colors, which is a property of the run, not of any one card. An explicit `color` or
       `rotation` attribute still wins when a block has a reason to break the sequence. */
    block-grid > collage-block:nth-child(6n + 1) {
        --collage-block-color: var(--color-red);
        --collage-block-rotation: -1.5deg;
    }

    block-grid > collage-block:nth-child(6n + 2) {
        --collage-block-color: var(--color-teal);
        --collage-block-rotation: 1.25deg;
    }

    block-grid > collage-block:nth-child(6n + 3) {
        --collage-block-color: var(--color-yellow);
        --collage-block-rotation: -0.75deg;
    }

    block-grid > collage-block:nth-child(6n + 4) {
        --collage-block-color: var(--color-green);
        --collage-block-rotation: 1.75deg;
    }

    block-grid > collage-block:nth-child(6n + 5) {
        --collage-block-color: var(--color-purple);
        --collage-block-rotation: -1.25deg;
    }

    block-grid > collage-block:nth-child(6n + 6) {
        --collage-block-color: var(--color-pink);
        --collage-block-rotation: 0.9deg;
    }

    /* An aside stacks two blocks that lean against each other rather than marching in a row. */
    content-stack > collage-block:nth-child(2n + 1) {
        --collage-block-rotation: -1.5deg;
    }

    content-stack > collage-block:nth-child(2n) {
        --collage-block-rotation: 1.75deg;
    }

    block-index {
        display: block;
        font-size: 0.8rem;
        letter-spacing: 0.16em;
        opacity: 0.7;
    }

    block-action {
        align-items: baseline;
        display: flex;
        gap: 0.75rem;
        justify-content: space-between;
        margin-block-start: auto;
        padding-block-start: 1rem;
    }

    block-action a {
        text-decoration: none;
    }

    /* The arrow is drawn rather than typed, so no content file carries a glyph whose only job is to say "this is a
       link", and a block whose action is plain text gets none. */
    block-action:has(a)::after {
        content: "→";
    }

    /* Stretching the anchor across its block makes the whole card clickable while the link itself keeps a meaningful
       name — wrapping the card in one anchor instead would announce the heading, the body copy, and the action as a
       single link. */
    block-action a::after {
        content: "";
        inset: 0;
        position: absolute;
    }

    collage-block:has(block-action a:hover) {
        rotate: 0deg;
        translate: 0 -0.5rem;
    }

    /* Lists */

    marker-list {
        display: block;
    }

    marker-list ul {
        display: flex;
        flex-direction: column;
        gap: 0.65rem;
    }

    /* The marker is absolutely positioned rather than a grid or flex sibling so that inline markup inside a row — an
       `<em>` publication name, a trailing link — stays part of the same text run and wraps with it. */
    marker-list li {
        padding-inline-start: 1.55rem;
        position: relative;
    }

    marker-list li::before {
        background-color: var(--page-accent-color);
        block-size: 0.7rem;
        border-radius: 50%;
        content: "";
        display: block;
        inline-size: 0.7rem;
        inset-block-start: 0.75em;
        inset-inline-start: 0;
        position: absolute;
        translate: 0 -50%;
    }

    marker-list li:nth-child(6n + 1)::before { background-color: var(--color-red); }
    marker-list li:nth-child(6n + 2)::before { background-color: var(--color-yellow); }
    marker-list li:nth-child(6n + 3)::before { background-color: var(--color-teal); }
    marker-list li:nth-child(6n + 4)::before { background-color: var(--color-green); }
    marker-list li:nth-child(6n + 5)::before { background-color: var(--color-purple); }
    marker-list li:nth-child(6n + 6)::before { background-color: var(--color-orange); }

    marker-list a {
        text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
    }

    marker-list a:hover {
        text-decoration-color: currentColor;
    }

    chip-list {
        display: block;
    }

    chip-list ul {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    chip-list li {
        background-color: var(--group-accent-color, var(--page-accent-color));
        border-radius: var(--chip-corner-radius);
        color: var(--ink-color);
        font-size: 0.85rem;
        letter-spacing: 0.04em;
        padding: 0.35em 0.9em;
    }

    /* One inherited hue ties a group's heading to its chips, so neither the heading nor any individual chip has to
       name a color. */
    block-grid > content-stack:nth-child(3n + 1) { --group-accent-color: var(--color-yellow); }
    block-grid > content-stack:nth-child(3n + 2) { --group-accent-color: var(--color-teal); }
    block-grid > content-stack:nth-child(3n + 3) { --group-accent-color: var(--color-pink); }

    block-grid > content-stack :is(h2, h3, h4) {
        color: var(--group-accent-color, currentColor);
    }

    /* Navigation within a page */

    page-subnav {
        display: block;
    }

    page-subnav ul {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    page-subnav li {
        display: contents;
    }

    page-subnav a {
        border: 2px solid color-mix(in srgb, var(--page-text-color) 35%, transparent);
        border-radius: var(--chip-corner-radius);
        font-size: 0.85rem;
        letter-spacing: 0.12em;
        padding: 0.45em 1.1em;
        text-decoration: none;
        text-transform: uppercase;
    }

    page-subnav a:hover {
        border-color: var(--page-text-color);
    }

    page-subnav a[aria-current] {
        background-color: var(--page-accent-color);
        border-color: var(--page-accent-color);
        color: var(--page-accent-text-color);
    }

    button-row {
        display: flex;
        flex-wrap: wrap;
        gap: 0.75rem;
    }

    button-row ul,
    button-row li {
        display: contents;
    }

    button-row a {
        align-items: center;
        background-color: var(--page-accent-color);
        border: 2px solid transparent;
        border-radius: var(--chip-corner-radius);
        color: var(--page-accent-text-color);
        display: inline-flex;
        gap: 0.6rem;
        letter-spacing: 0.06em;
        padding: 0.7em 1.4em;
        text-decoration: none;
        text-transform: uppercase;
        transition: rotate 200ms ease, scale 200ms ease;
    }

    button-row a:hover {
        rotate: -1.5deg;
        scale: 1.03;
    }

    /* The first action is the one being asked for; anything after it is an alternative, and takes the outline. */
    button-row li:not(:first-child) a {
        background-color: transparent;
        border-color: currentColor;
        color: var(--page-text-color);
    }

    /* Decoration */

    /* A band of gel color, sorted by hue. Hard gradient stops rather than a row of elements: the strip says nothing,
       so it costs the content file nothing and needs no markup to exist. */
    gel-strip {
        background-image: linear-gradient(
            to right,
            #FFD9B0 0 8.3333%,
            #FF8A18 8.3333% 16.6667%,
            #E8202A 16.6667% 25%,
            #E33F86 25% 33.3333%,
            #7A2E9E 33.3333% 41.6667%,
            #2A1276 41.6667% 50%,
            #123C9E 50% 58.3333%,
            #0F7FC4 58.3333% 66.6667%,
            #21B6B8 66.6667% 75%,
            #0F7A3C 75% 83.3333%,
            #6FC24A 83.3333% 91.6667%,
            #FFE23A 91.6667% 100%
        );
        block-size: clamp(3.5rem, 7vw, 6rem);
        display: block;
        grid-column: full;
    }

    /* Ticker of butted color blocks, marching sideways under the hero. */
    scrolling-marquee {
        --marquee-duration: 26s;

        background-color: var(--ink-color);
        border-block: 3px solid var(--ink-color);
        display: flex;
        overflow: hidden;
        padding-block: 0.35rem;
    }

    scrolling-marquee ul {
        display: flex;
        flex: none;
        inline-size: max-content;
    }

    /* Each list travels its own full width, which lands the copy exactly where the original started. The spacing is a
       trailing margin on the items rather than a gap on the list, so that a list's width includes the space that
       follows it and the two copies butt together at the same rhythm as the blocks inside them. */
    scrolling-marquee[looping] ul {
        animation: marquee-scroll var(--marquee-duration) linear infinite;
        will-change: transform;
    }

    @keyframes marquee-scroll {
        from {
            transform: translateX(0);
        }

        to {
            transform: translateX(-100%);
        }
    }

    scrolling-marquee li {
        background-color: var(--marquee-item-color, var(--color-yellow));
        color: var(--ink-color);
        font-size: clamp(1.1rem, 0.9rem + 1vw, 1.75rem);
        font-variation-settings: "SCTR" 90, "JMBL" 205, "COUT" 135;
        margin-inline-end: 0.35rem;
        padding: 0.25em 0.9em;
        text-transform: uppercase;
        white-space: nowrap;
    }

    scrolling-marquee li:nth-child(8n + 1) { --marquee-item-color: var(--color-red); }
    scrolling-marquee li:nth-child(8n + 2) { --marquee-item-color: var(--color-orange); }
    scrolling-marquee li:nth-child(8n + 3) { --marquee-item-color: var(--color-yellow); }
    scrolling-marquee li:nth-child(8n + 4) { --marquee-item-color: var(--color-green); }
    scrolling-marquee li:nth-child(8n + 5) { --marquee-item-color: var(--color-teal); }
    scrolling-marquee li:nth-child(8n + 6) { --marquee-item-color: var(--color-blue); color: var(--paper-color); }
    scrolling-marquee li:nth-child(8n + 7) { --marquee-item-color: var(--color-purple); }
    scrolling-marquee li:nth-child(8n + 8) { --marquee-item-color: var(--color-pink); }
}
