body {
  margin: 0;
  background-color: #ffffff;
}

/* frame and caption sit together in the middle of the page */
.piece {
  min-height: 100vh;
  box-sizing: border-box;
  padding: 2rem 1rem;

  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1.5rem;
}

.change {
  animation: grow 10s ease-in-out forwards;
  /* animation-name: grow; */
}

@keyframes grow {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(1.5);
  }
}

.artcontainer  {
  display: flex;
  justify-content: center;
}

.picCard {
    position: relative;
    overflow: hidden;

    /* 16:9 canvas, capped at the old 500px max height, and short enough that
       the frame (17.4% of the canvas height) plus a two-line caption fit on screen */
    --canvas-width: min(72vw, 889px, calc((100vh - 18rem) / 1.174 * 16 / 9));
    --canvas-long-side: var(--canvas-width);
    width: var(--canvas-width);
    aspect-ratio: 16 / 9;

    /* gold frame: slicing at its 89px border keeps the corners crisp while the
       straight edges stretch; thickness is 4.9% of the long side, as in the image */
    border-style: solid;
    border-width: calc(var(--canvas-long-side) * 0.049);
    border-image: url("frame.webp") 89 stretch;

    /* blank canvas before the first artwork */
    background-color: rgb(202, 174, 129);
}

/* the artwork itself: 144 pixels drawn as a 16 x 9 grid (9 x 16 in portrait),
   and smudgeable by dragging (see PicList.js) */
.picCanvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    /* dragging on the artwork smudges it instead of scrolling the page */
    touch-action: none;
    cursor: crosshair;
}

/* faint outline of the smudge brush under the mouse */
.brush-ring {
    position: absolute;
    top: 0;
    left: 0;
    border: 1px solid rgba(255, 255, 255, 0.7);
    border-radius: 50%;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
    pointer-events: none;
    opacity: 0;
}

/* taller-than-wide screens get a 9:16 canvas: the same 144 pixels in the same
   order, wrapping after 9 columns into 16 rows */
@media (orientation: portrait) {
    .picCard {
        /* 70vw leaves room for the frame, which is much thicker relative to a narrow canvas */
        --canvas-width: min(70vw, 500px, calc((100vh - 18rem) / 1.098 * 9 / 16));
        --canvas-long-side: calc(var(--canvas-width) * 16 / 9);
        aspect-ratio: 9 / 16;
    }
}

/* caption in the hand-lettered spirit of Magritte's "Ceci n'est pas une pipe" */
.title {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.1em 0.3em;

  /* when the caption and the typed words outgrow this, the blank wraps onto its
     own centered line */
  max-width: calc(100vw - 4rem);
  /* Sirivennela's line box runs 0.27em below its lowest descenders; pulling that
     in centers the frame and caption by what's visible, not by empty space */
  margin: 0 auto -0.27em;

  font-family: 'Sirivennela', cursive;
  /* Sirivennela runs small and tightly spaced, so size it up and open the word gaps */
  font-size: clamp(2.25rem, 6.5vw, 4.5rem);
  word-spacing: 0.15em;
  color: #1a1a1a;
  /* the example words and Enter arrow */
  --ink-faint: rgba(26, 26, 26, 0.3);
}

/* holds the blank; its width is set from .blank-sizer (see PicSearchPaginate.js)
   and eases between sizes, so the centered caption glides as letters come and go */
.entry {
    display: inline-flex;
    align-items: baseline;
    max-width: 100%;
    /* pulls back the input's text-indent and right padding, so they only make
       room for strokes and the cursor, and centering goes by the text itself */
    margin-left: -0.22em;
    margin-right: -0.1em;
    transition: width 160ms ease-out;
}

.caption {
    white-space: nowrap;
}

/* the blank takes its new width at once (it doesn't shrink while .entry
   catches up), so letters are never clipped */
.blank {
    position: relative;
    display: inline-block;
    flex: none;
    max-width: calc(100vw - 6rem);
}

/* the example word, faint, starting right where the cursor sits */
.example {
    position: absolute;
    top: 0;
    left: 0;
    padding-left: 0.22em;
    white-space: pre;
    color: var(--ink-faint);
    pointer-events: none;
    transition: opacity 150ms ease-out;
}

.example.is-hidden {
    opacity: 0;
}

/* invisible copy of the blank's text, measured for the blank's width */
.blank-sizer {
    position: absolute;
    top: 0;
    left: 0;
    width: max-content;
    visibility: hidden;
    white-space: pre;
    pointer-events: none;
    /* matches the input's padding plus text-indent */
    padding: 0 0.1em 0 0.22em;
}

@media (prefers-reduced-motion: reduce) {
    .entry,
    .example,
    .enter {
        transition: none;
    }
}

.search {
    display: block;
    width: 100%;
    min-width: 0;

    outline: 0;
    border: 0;
    border-radius: 0;
    background: transparent;

    font: inherit;
    word-spacing: inherit;
    color: inherit;
    caret-color: #1a1a1a;

    /* room on the right for the cursor and for letters whose strokes reach
       past their width (up to 0.09em, on T) */
    padding: 0 0.1em 0 0;
    /* inputs clip typed text at their content edge, and the script's lead-in
       strokes reach 0.21em left of the letter, so indent past them */
    text-indent: 0.22em;
}

/* hangs just past the end of the text, outside the width that's centered; its
   bottom sits on the baseline (0.42em above the blank's bottom, less padding) */
.enter {
    position: absolute;
    left: calc(100% - 0.05em);
    bottom: 0.32em;
    /* buttons don't inherit font size, which the arrow's em sizing relies on */
    font-size: inherit;
    padding: 0.1em;
    border: 0;
    background: none;
    color: var(--ink-faint);
    cursor: pointer;
    line-height: 0;
    transition: opacity 150ms ease-out, color 150ms ease-out;
}

/* nothing new to make art from: the blank is empty, or unchanged since Enter */
.enter.is-hidden {
    opacity: 0;
    cursor: default;
}

.enter:hover,
.enter:focus-visible {
    color: #1a1a1a;
}

.enter svg {
    width: 0.45em;
    height: 0.45em;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}


/* wall text below the artwork: small, grey, sans-serif */
.statement {
    max-width: 34rem;
    /* rises toward the caption; the exact amount is set by
       useRiseTowardCaption in ArtistStatement.js */
    margin: -2rem auto 0;
    padding: 0 1.5rem 6rem;

    font-family: 'Libre Franklin', Arial, Helvetica, sans-serif;
    font-weight: 300;
    font-size: 0.9rem;
    line-height: 1.65;
    color: #6b6b6b;
}

.statement p {
    margin: 0 0 1.1em;
}

/* the essay's title: same quiet sans-serif, a step up in size and weight */
.statement-heading {
    /* the same gap above and below: the paragraph above ends with a 1.1em
       (0.99rem) margin, so the heading's own margin matches it below */
    margin: 0 0 0.99rem;
    font-size: 1.05rem;
    font-weight: 400;
    line-height: 1.4;
    color: #4a4a4a;
    text-wrap: balance;
}

.site-link {
    color: #2f5fb3;
    text-decoration: none;
}

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

/* the site's favicon in a small circle; the light disc shows the circle even
   when a favicon has a transparent background */
.site-icon {
    box-sizing: border-box;
    width: 1.25em;
    height: 1.25em;
    margin-right: 0.3em;
    padding: 0.18em;
    border-radius: 50%;
    background-color: #ececec;
    object-fit: contain;
    vertical-align: -0.3em;
}

/* a tiny copy of a painting, as tall as the line of text, at its own 4:3 shape */
.artwork-thumb {
    height: 0.94em;
    width: auto;
    aspect-ratio: 4 / 3;
    margin-right: 0.3em;
    border-radius: 2px;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
    vertical-align: -0.1em;
}

/* spoiler hidden under a smudge of its own ink: each letter is transparent and
   only its smeared, blurred shadow shows. When revealed, every letter fades in
   at its own random moment (--delay) while its smudge fades to nothing */
.spoiler {
    --smudge-strong: rgba(107, 107, 107, 0.5);
    --smudge: rgba(107, 107, 107, 0.28);
    --smudge-faint: rgba(107, 107, 107, 0.14);
    cursor: pointer;
    user-select: none;
    border-radius: 3px;
}

.spoiler:focus-visible {
    outline: 1px dashed #6b6b6b;
    outline-offset: 2px;
}

.spoiler-char {
    color: transparent;
    /* each letter drags a trail of ink to the right; the trails run together
       into smeared streaks along every line, like a finger pulled through paint */
    text-shadow:
        0 0 3.5px var(--smudge-strong),
        4px 0 4px var(--smudge-strong),
        9px 0 4.5px var(--smudge),
        15px 0 5px var(--smudge),
        22px 0 6px var(--smudge-faint),
        30px 0 7px var(--smudge-faint);
}

.spoiler.is-revealed {
    cursor: auto;
    user-select: auto;
}

.spoiler.is-revealed .spoiler-char {
    color: inherit;
    text-shadow:
        0 0 3.5px transparent,
        4px 0 4px transparent,
        9px 0 4.5px transparent,
        15px 0 5px transparent,
        22px 0 6px transparent,
        30px 0 7px transparent;
    transition: color 280ms ease-out, text-shadow 420ms ease-out;
    transition-delay: var(--delay);
}

@media (prefers-reduced-motion: reduce) {
    .spoiler.is-revealed .spoiler-char {
        transition: none;
    }
}

/* iMessage-style ripple: a wave travels across the letters, then rests */
.ripple {
    white-space: nowrap;
}

.ripple-char {
    display: inline-block;
    animation: ripple 2.4s ease-in-out 1;
    animation-delay: calc(var(--i) * 70ms);
}

@keyframes ripple {
    0%,
    30%,
    100% {
        transform: translateY(0);
    }
    10% {
        transform: translateY(-0.28em);
    }
    20% {
        transform: translateY(0.06em);
    }
}

@media (prefers-reduced-motion: reduce) {
    .ripple-char {
        animation: none;
    }
}

/* when the essay was written, signed off at the end like a letter */
.statement-date {
    margin-top: 1.8em;
    font-size: 0.8rem;
    color: #8a8a8a;
    font-variant-numeric: tabular-nums;
}

/* the artist's recorded smudge, drawn over the spoiler (see SmudgedSpoiler.js);
   the paragraph is its positioning box */
.statement p {
    position: relative;
}

.spoiler {
    --ink: #6b6b6b;
}

/* under the canvas the real letters are simply invisible, no shadow smear */
.spoiler.uses-canvas .spoiler-char {
    text-shadow: none;
}

.spoiler-canvas {
    position: absolute;
    /* reaches past the paragraph, so smudges can run off its edges */
    top: -2.5em;
    left: -2.5em;
    width: calc(100% + 5em);
    height: calc(100% + 5em);
    pointer-events: none;
    transition: opacity 1600ms ease-in;
}

.spoiler-canvas.is-studio {
    pointer-events: auto;
    cursor: crosshair;
    touch-action: none;
}

.spoiler-canvas.is-revealed {
    opacity: 0;
}

/* studio mode note, pinned to the corner of the screen */
.spoiler-studio {
    position: fixed;
    left: max(12px, env(safe-area-inset-left, 0px));
    bottom: max(12px, env(safe-area-inset-bottom, 0px));
    z-index: 10;
    max-width: 22rem;
    padding: 0.6rem 0.8rem;
    border-radius: 6px;
    background: #1a1a1a;
    color: #f2f2f2;
    font-size: 0.8rem;
    line-height: 1.4;
}

.spoiler-studio button {
    margin-left: 0.3em;
    padding: 0.1em 0.5em;
    border: 1px solid #f2f2f2;
    border-radius: 4px;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.spoiler-studio button:disabled {
    opacity: 0.4;
    cursor: default;
}

/* words kept on top of the spoiler's smudge, so it can pass under them */
.above-smudge {
    position: relative;
    z-index: 1;
}

.spoiler-canvas {
    z-index: 0;
}

/* iMessage-style effects on single words (see TextEffect.js) */
.effect {
    white-space: nowrap;
}

.effect-char {
    display: inline-block;
    animation-delay: calc(var(--i) * 60ms);
    animation-iteration-count: 1;
    animation-timing-function: ease-in-out;
}

/* bloom: each letter swells a little and glows, then settles */
.effect-bloom .effect-char {
    animation-name: bloom;
    animation-duration: 3s;
}

@keyframes bloom {
    0%,
    40%,
    100% {
        transform: scale(1);
        text-shadow: 0 0 0 rgba(107, 107, 107, 0);
    }
    18% {
        transform: scale(1.18);
        text-shadow: 0 0 0.35em rgba(107, 107, 107, 0.55);
    }
}

/* small: the whole phrase shrinks toward its baseline as one piece (letters
   shrinking on their own would leave gaps), holds, then grows back */
.effect-small {
    display: inline-block;
    transform-origin: 50% 85%;
    animation: small 4s ease-in-out 1;
}

.effect-small .effect-char {
    animation: none;
}

@keyframes small {
    0%,
    60%,
    100% {
        transform: scale(1);
    }
    15%,
    40% {
        transform: scale(0.72);
    }
}

@media (prefers-reduced-motion: reduce) {
    .effect-char {
        animation: none;
    }
}

/* each effect plays once on load, and again whenever the word is hovered.
   Hover switches to an identical copy of the animation, which restarts it */
.ripple:hover .ripple-char {
    animation-name: ripple-again;
}

.effect-bloom:hover .effect-char {
    animation-name: bloom-again;
}

.effect-small:hover {
    animation-name: small-again;
}

@keyframes ripple-again {
    0%, 30%, 100% { transform: translateY(0); }
    10% { transform: translateY(-0.28em); }
    20% { transform: translateY(0.06em); }
}

@keyframes bloom-again {
    0%, 40%, 100% { transform: scale(1); text-shadow: 0 0 0 rgba(107, 107, 107, 0); }
    18% { transform: scale(1.18); text-shadow: 0 0 0.35em rgba(107, 107, 107, 0.55); }
}

@keyframes small-again {
    0%, 60%, 100% { transform: scale(1); }
    15%, 40% { transform: scale(0.72); }
}

@media (prefers-reduced-motion: reduce) {
    .ripple:hover .ripple-char,
    .effect:hover .effect-char {
        animation: none;
    }
}

/* big: the whole word swells from its center, holds a beat, then settles */
.effect-big {
    display: inline-block;
    transform-origin: 50% 50%;
    animation: big 1.8s ease-in-out 1;
}

.effect-big .effect-char {
    animation: none;
}

.effect-big:hover {
    animation-name: big-again;
}

@keyframes big {
    0%, 100% { transform: scale(1); }
    25%, 55% { transform: scale(1.7); }
}

@keyframes big-again {
    0%, 100% { transform: scale(1); }
    25%, 55% { transform: scale(1.7); }
}

@media (prefers-reduced-motion: reduce) {
    .effect-big,
    .effect-big:hover {
        animation: none;
    }
}

/* after the un-smudge the canvas already shows clean text, so the real text
   takes over at once: no letter-by-letter fade, no canvas fade */
.spoiler.is-unsmudged .spoiler-char {
    transition: none;
}

.spoiler-canvas.is-unsmudged {
    transition: none;
    opacity: 0;
}

/* rub or tap to reveal: dragging on the smudge wipes it instead of scrolling */
.rub-area .spoiler,
.rub-area .spoiler-canvas {
    cursor: grab;
}

/* on touch screens, dragging in the spoiler paragraph wipes instead of scrolling */
.rub-area {
    touch-action: none;
}


/* a soft white fade along the bottom of the screen, so text dissolves into the
   page as it scrolls under the edge */
.page-scrim {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(4.5rem + env(safe-area-inset-bottom, 0px));
    background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #ffffff 85%);
    pointer-events: none;
    z-index: 5;
}

@media (prefers-reduced-motion: reduce) {
    .effect-small,
    .effect-small:hover {
        animation: none;
    }
}

/* read the essay aloud: a quiet button after the date, that becomes a pause
   button with a progress line and the time while it speaks */
.listen {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.6rem;
    font-size: 0.8rem;
    color: #8a8a8a;
}

.listen button {
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
}

.listen-button {
    display: inline-flex;
    align-items: center;
    gap: 0.45em;
}

.listen-button:hover,
.listen-button:focus-visible,
.listen-stop:hover,
.listen-stop:focus-visible {
    color: #4a4a4a;
}

.listen-icon {
    font-size: 0.7em;
}

.listen-progress {
    position: relative;
    flex: 1 1 6rem;
    max-width: 12rem;
    height: 2px;
    border-radius: 1px;
    background: #e2e2e2;
    overflow: hidden;
}

.listen-progress-fill {
    position: absolute;
    inset: 0 auto 0 0;
    background: #8a8a8a;
    transition: width 250ms linear;
}

.listen-time {
    font-variant-numeric: tabular-nums;
}

.listen-stop {
    font-size: 0.7em;
}

/* the listen button is a full-width black bar under the essay; while it
   speaks, the progress line, time and stop sit on a row beneath it */
.listen {
    margin-top: 1.4rem;
}

.listen .listen-button {
    flex: 1 1 100%;
    justify-content: center;
    padding: 0.75rem 1rem;
    border-radius: 6px;
    background: #1a1a1a;
    color: #ffffff;
    font-size: 0.85rem;
    font-weight: 400;
}

.listen .listen-button:hover,
.listen .listen-button:focus-visible {
    background: #333333;
    color: #ffffff;
}

.listen .listen-button:focus-visible {
    outline: 2px solid #1a1a1a;
    outline-offset: 2px;
}

.listen .listen-progress {
    max-width: none;
}

/* while listening, the whole bar is black and holds every control: pause,
   progress, time, speed and stop */
.listen.is-active {
    flex-wrap: nowrap;
    gap: 0.75rem;
    padding: 0.55rem 0.9rem;
    border-radius: 6px;
    background: #1a1a1a;
    color: #e6e6e6;
}

.listen.is-active .listen-button {
    flex: none;
    padding: 0.15rem 0.2rem;
    background: none;
}

.listen.is-active .listen-button:hover,
.listen.is-active .listen-button:focus-visible {
    background: none;
    color: #ffffff;
}

.listen.is-active .listen-button:focus-visible,
.listen.is-active .listen-rate:focus-visible,
.listen.is-active .listen-stop:focus-visible {
    outline: 1px solid #ffffff;
    outline-offset: 2px;
}

.listen.is-active .listen-progress {
    flex: 1 1 auto;
    background: rgba(255, 255, 255, 0.22);
}

.listen.is-active .listen-progress-fill {
    background: #ffffff;
}

.listen.is-active .listen-time {
    white-space: nowrap;
    font-size: 0.78rem;
}

.listen-rate {
    padding: 0.1rem 0.15rem;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 4px;
    background: transparent;
    color: inherit;
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.listen-rate option {
    color: #1a1a1a;
}

.listen.is-active .listen-stop:hover {
    color: #ffffff;
}

/* the black bar is one fixed size whether idle or playing: the bar itself is
   the black box, and the idle button simply fills it */
.listen,
.listen.is-active {
    box-sizing: border-box;
    flex-wrap: nowrap;
    height: 2.75rem;
    padding: 0 0.9rem;
    border-radius: 6px;
    background: #1a1a1a;
    color: #e6e6e6;
}

.listen:not(.is-active) {
    padding: 0;
}

.listen:not(.is-active) .listen-button {
    flex: 1 1 100%;
    align-self: stretch;
    height: 100%;
    padding: 0 1rem;
    background: none;
    border-radius: 6px;
}

.listen:not(.is-active):hover,
.listen:not(.is-active):focus-within {
    background: #333333;
}

.listen:not(.is-active) .listen-button:hover,
.listen:not(.is-active) .listen-button:focus-visible {
    background: none;
}

/* the play, pause and stop icons */
.listen-svg {
    display: block;
    width: 0.95rem;
    height: 0.95rem;
    fill: currentColor;
    flex: none;
}

.listen:not(.is-active) .listen-button {
    gap: 0.55em;
}

.listen-stop .listen-svg {
    width: 0.85rem;
    height: 0.85rem;
}

.listen-stop {
    display: inline-flex;
    align-items: center;
}

/* nothing widens the page sideways (the spoiler's smudge canvas reaches past
   its paragraph, and on phones past the screen edge); clip, unlike hidden,
   doesn't make the page its own scroll box */
html,
body {
    overflow-x: clip;
}

/* the blank is a text area so long text wraps; it looks like a one-line field */
textarea.search {
    resize: none;
    overflow: hidden;
    line-height: inherit;
    white-space: pre-wrap;
    overflow-wrap: break-word;
    /* wrapped lines center under the caption, like the rest of it */
    text-align: center;
}

/* phones: "Ceci n'est pas une" on its own line and the blank centered below it,
   so the caption doesn't jump between one and two lines as examples change */
@media (max-width: 600px) {
    .title .caption {
        flex-basis: 100%;
        text-align: center;
    }
}

.link-lead {
    white-space: nowrap;
}
