/* ============================================================
   DONDA — public landing page
   Palette sampled directly from pfporiginal.png. Deliberately
   monochrome: the only "second colour" is inversion (bone fill,
   red text), which is also how a flagged OCR token is drawn.
   ============================================================ */

@font-face {
    font-family: 'Archivo';
    src: url('assets/fonts/archivo-var-latin.woff2') format('woff2-variations');
    font-weight: 400 900;
    font-stretch: 62% 125%;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plex Sans';
    src: url('assets/fonts/plex-sans-var-latin.woff2') format('woff2-variations');
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plex Mono';
    src: url('assets/fonts/plex-mono-400-latin.woff2') format('woff2');
    font-weight: 400;
    font-style: normal;
    font-display: swap;
}
@font-face {
    font-family: 'Plex Mono';
    src: url('assets/fonts/plex-mono-600-latin.woff2') format('woff2');
    font-weight: 600;
    font-style: normal;
    font-display: swap;
}

:root {
    --field:    #e71739;   /* the pfp's ground */
    --field-lo: #c4132a;
    --deep:     #7c0e14;
    --void:     #240406;
    --void-2:   #2e070a;
    --bone:     #f7f1ec;
    --bone-70:  rgba(247, 241, 236, .70);
    --bone-42:  rgba(247, 241, 236, .42);
    --bone-16:  rgba(247, 241, 236, .16);

    --display: 'Archivo', 'Arial Narrow', Impact, sans-serif;
    --body: 'Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --mono: 'Plex Mono', ui-monospace, 'Cascadia Mono', Consolas, monospace;

    --gutter: clamp(1.25rem, 5vw, 4rem);
    --measure: 1180px;
    --band-y: clamp(4.5rem, 10vw, 8.5rem);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
    margin: 0;
    background: var(--void);
    color: var(--bone);
    font-family: var(--body);
    font-size: clamp(1rem, .96rem + .22vw, 1.1rem);
    line-height: 1.62;
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
}

img { max-width: 100%; height: auto; display: block; }

a { color: inherit; }

:focus-visible {
    outline: 2px solid var(--bone);
    outline-offset: 3px;
    border-radius: 2px;
}

.skip {
    position: absolute;
    left: -9999px;
    top: 0;
    background: var(--bone);
    color: var(--field);
    padding: .75rem 1.1rem;
    font-family: var(--mono);
    font-size: .85rem;
    z-index: 20;
}
.skip:focus { left: .75rem; top: .75rem; }

/* ── shared type ─────────────────────────────────────────── */

.display {
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 74%;
    text-transform: uppercase;
    line-height: .92;
    letter-spacing: -.005em;
    margin: 0;
    text-wrap: balance;
}

.display-2 { font-size: clamp(2rem, 1.2rem + 3.6vw, 3.5rem); }

/*
 * Small text on this page comes in two voices and they should not look alike.
 *
 * Mono, tracked, uppercase is reserved for machine output and technical
 * identifiers: the OCR readout, the flag chips, the names of the detection
 * layers. Anything written in the site's own voice uses the body face — the
 * eyebrow below, and the labels in the privacy table, which are really just
 * small headings and are marked up as such.
 */
.eyebrow {
    font-family: var(--body);
    font-size: .95rem;
    color: var(--bone-70);
    margin: 0 0 1.1rem;
}

.tag {
    font-family: var(--mono);
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--bone-42);
    margin: 0;
}

/* the site's voice, not the machine's */
.privacy-label {
    font-family: var(--display);
    font-weight: 700;
    font-stretch: 88%;
    font-size: 1.15rem;
    line-height: 1.2;
    letter-spacing: .005em;
    color: var(--bone);
    margin: 0;
}

.mono-inline {
    font-family: var(--mono);
    font-size: .92em;
    background: var(--bone-16);
    padding: .08em .34em;
    border-radius: 2px;
    white-space: nowrap;
}

.band {
    padding-block: var(--band-y);
    padding-inline: var(--gutter);
}

.band-head { max-width: 46rem; margin: 0 0 clamp(2.5rem, 5vw, 4rem); }

.band-intro {
    color: var(--bone-70);
    font-size: 1.06rem;
    max-width: 42rem;
    margin: 1.2rem 0 0;
}

.outcome {
    font-family: var(--body);
    color: var(--bone-70);
    border-top: 1px solid var(--bone-16);
    padding-top: 1.6rem;
    margin: clamp(2.5rem, 5vw, 3.5rem) auto 0;
    max-width: var(--measure);
}
.outcome strong { color: var(--bone); font-weight: 600; }

/* ── the button (one label, repeated) ────────────────────── */

.btn {
    display: inline-block;
    background: var(--bone);
    color: var(--field);
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 82%;
    text-transform: uppercase;
    letter-spacing: .01em;
    text-decoration: none;
    padding: .95rem 1.6rem .85rem;
    box-shadow: 6px 6px 0 var(--void);
    transition: transform .16s ease, box-shadow .16s ease;
}
.btn:hover { transform: translate(-2px, -2px); box-shadow: 9px 9px 0 var(--void); }
.btn:active { transform: translate(2px, 2px); box-shadow: 3px 3px 0 var(--void); }

.btn-lg { font-size: clamp(1.05rem, .95rem + .5vw, 1.35rem); }
.btn-sm {
    font-size: .84rem;
    padding: .6rem 1rem .52rem;
    box-shadow: 4px 4px 0 var(--void);
}
.btn-sm:hover { box-shadow: 6px 6px 0 var(--void); }

.microcopy {
    font-size: .92rem;
    color: var(--bone-70);
    margin: 1.15rem 0 0;
    max-width: 30rem;
}

/* ── masthead ────────────────────────────────────────────── */

.masthead {
    background: var(--field);
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.1rem var(--gutter);
}

.brand {
    display: flex;
    align-items: center;
    gap: .7rem;
    text-decoration: none;
}

.brand-mark {
    width: 38px;
    height: 38px;
    border-radius: 9px;
}

.brand-name {
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 70%;
    font-size: 1.4rem;
    letter-spacing: .04em;
}

/* ── hero ────────────────────────────────────────────────── */

.hero {
    background: var(--field);
    display: grid;
    grid-template-columns: minmax(0, 1.02fr) minmax(0, .98fr);
    gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: center;
    max-width: none;
    position: relative;
    padding-top: clamp(2.5rem, 5vw, 4rem);
    padding-bottom: calc(var(--band-y) + 5vw);
    /* folded-paper cut, echoing the mark */
    clip-path: polygon(0 0, 100% 0, 100% calc(100% - 5vw), 0 100%);
}

/*
 * The cut on its own is just an angled edge, which is not what the mark does —
 * the mark is a ribbon whose planes turn and catch different light. These are
 * the creases: a narrow darker band riding the cut so the red reads as a sheet
 * turning over, rather than as a diagonal wipe between two colours.
 */
.hero::after,
.closer::before {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--deep);
    pointer-events: none;
    /* clip-path makes both sections stacking contexts, so this sits above the
       section's own background and below its content */
    z-index: -1;
}

.hero::after {
    clip-path: polygon(0 100%, 100% calc(100% - 5vw),
                       100% calc(100% - 6.1vw), 0 calc(100% - 1.1vw));
}

.closer::before {
    clip-path: polygon(0 5vw, 100% 0, 100% 1.1vw, 0 calc(5vw + 1.1vw));
}

.hero > * { max-width: 100%; }

.hero-copy { max-width: 34rem; justify-self: end; width: 100%; }

h1.display { font-size: clamp(2.6rem, 1.2rem + 5.4vw, 4.9rem); }

/* the highlight is the page's core idea: a token the scanner pulled out */
h1.display em {
    font-style: normal;
    display: inline-block;
    background: var(--bone);
    color: var(--field);
    padding: 0 .18em .06em;
}

.lede {
    font-size: clamp(1.05rem, 1rem + .3vw, 1.2rem);
    color: var(--bone);
    margin: 1.5rem 0 2rem;
    max-width: 33rem;
}

/* ── the scanner (signature element) ─────────────────────── */

.scanner { margin: 0; width: 100%; max-width: 30rem; justify-self: start; }

.poster {
    position: relative;
    aspect-ratio: 4 / 3;
    background:
        radial-gradient(120% 90% at 20% 0%, #3d080d 0%, var(--void) 62%);
    border: 1px solid var(--bone-16);
    overflow: hidden;
    display: grid;
    place-items: center;
    text-align: center;
}

.poster-inner {
    padding: 1.4rem;
}

.poster-kicker {
    font-family: var(--mono);
    font-size: .62rem;
    letter-spacing: .24em;
    text-transform: uppercase;
    color: var(--bone-42);
    margin: 0 0 .5rem;
}

/* OCR merges these two lines into one, so they share one box. */
.poster-headline { margin: 0 0 .9rem; }

.poster-amount {
    font-family: var(--display);
    font-weight: 900;
    font-stretch: 68%;
    font-size: clamp(3rem, 11vw, 4.6rem);
    line-height: .82;
    margin: 0;
    color: var(--bone);
}

.poster-word {
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 68%;
    text-transform: uppercase;
    font-size: clamp(1.5rem, 5.4vw, 2.2rem);
    letter-spacing: .22em;
    line-height: 1;
    margin: .3rem 0 0;
    color: var(--field);
}

.poster-band {
    font-family: var(--mono);
    font-size: .66rem;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--bone-70);
    margin: 0;
}

.poster-cta {
    display: inline-block;
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 84%;
    text-transform: uppercase;
    font-size: .82rem;
    letter-spacing: .06em;
    color: var(--void);
    background: var(--bone);
    padding: .42rem .9rem .34rem;
    border-radius: 999px;
    margin: 1rem 0 0;
}

.poster-foot {
    font-family: var(--mono);
    font-size: .6rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--bone-42);
    margin: .7rem 0 0;
}

/*
 * Detected text regions. The outline is always present and always transparent,
 * so nothing reflows when it comes up; only its colour is animated.
 */
.ocr-region {
    width: fit-content;
    margin-inline: auto;
    outline: 1px solid transparent;
    outline-offset: 3px;
}

.ocr-region.is-flag {
    outline-width: 2px;
    outline-offset: 4px;
}

.verdict-stamp {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    opacity: 0;
    background: rgba(36, 4, 6, .3);
}
.verdict-stamp span {
    font-family: var(--display);
    font-weight: 800;
    font-stretch: 78%;
    text-transform: uppercase;
    font-size: clamp(1rem, 4vw, 1.5rem);
    letter-spacing: .04em;
    color: var(--bone);
    border: 3px solid var(--bone);
    padding: .4rem 1rem .3rem;
    transform: rotate(-7deg);
}

.readout {
    background: var(--void);
    border: 1px solid var(--bone-16);
    border-top: 0;
    padding: 1.1rem 1.2rem 1.25rem;
    font-family: var(--mono);
    font-size: .78rem;
    line-height: 1.5;
}

.readout-head {
    margin: 0 0 .8rem;
    font-size: .66rem;
    font-weight: 600;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--bone-42);
}

.ocr-lines {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: .34rem;
}

.ocr-line { color: var(--bone-70); }
.ocr-line.flagged { color: var(--bone); }

.chip {
    display: inline-block;
    background: var(--bone);
    color: var(--field);
    font-weight: 600;
    font-size: .62rem;
    letter-spacing: .14em;
    text-transform: uppercase;
    padding: .1rem .4rem;
    margin-left: .3rem;
    vertical-align: 1px;
}

.readout-note {
    margin: .8rem 0 0;
    color: var(--bone-42);
}
.readout-note strong { color: var(--bone); }

.readout-verdict {
    margin: .55rem 0 0;
    padding-top: .7rem;
    border-top: 1px solid var(--bone-16);
    color: var(--bone);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .08em;
    font-size: .7rem;
}

.scanner-caption {
    margin: 1rem 0 0;
    font-size: .82rem;
    line-height: 1.5;
    color: var(--bone-70);
    font-family: var(--body);
    max-width: 28rem;
}

/*
 * Motion, in two beats rather than a steady drip.
 *
 * Beat one (0 - 0.4s): every region and every extracted line lands almost at
 * once, because that is what an OCR pass actually returns — a whole result, not
 * a line at a time. Then nothing happens for half a second.
 *
 * Beat two (from 1.15s): judgement. Two boxes go solid, the chips land, the
 * count and the verdict follow, and the message goes.
 *
 * The pause is the point. The extraction is not the impressive part; deciding
 * that two ordinary-looking phrases cost the message is.
 */
/* scoped to the scanner: the chip style is reused in the QR exhibit further
   down the page, which is static and must not start hidden */
.js .scanner .ocr-line,
.js .scanner .chip,
.js .scanner .readout-note,
.js .scanner .readout-verdict,
.js .scanner .verdict-stamp { opacity: 0; }

/* beat one — the read.
   The second animation is the ending: everything the bot cleared falls away,
   so the two phrases that actually cost the message are what's left lit. */
.js .scanner.is-running .ocr-region {
    animation: box-found .2s ease calc(.06s + var(--i) * .06s) forwards,
               fade-back .5s ease 1.94s forwards;
}

.js .scanner.is-running .ocr-line {
    animation: found .18s ease forwards;
    animation-delay: calc(.14s + var(--i) * .05s);
}

/* beat two — the judgement. Flagged regions get only this one animation, so
   they are deliberately exempt from the fade above. */
.js .scanner.is-running .ocr-region.is-flag {
    animation: box-flag 1.5s ease calc(.06s + var(--i) * .06s) forwards;
}

.js .scanner.is-running .chip {
    animation: pop .22s ease forwards;
    animation-delay: calc(1.18s + (var(--i) - 3) * .12s);
}

.js .scanner.is-running .readout-note {
    animation: found .2s ease forwards;
    animation-delay: 1.55s;
}

.js .scanner.is-running .readout-verdict {
    animation: found .2s ease forwards;
    animation-delay: 1.86s;
}

.js .scanner.is-running .verdict-stamp {
    animation: stamp .3s ease forwards;
    animation-delay: 1.94s;
}

@keyframes found { to { opacity: 1; } }
@keyframes box-found { to { outline-color: rgba(247, 241, 236, .26); } }

/* one animation carries both beats, so the pause is explicit rather than a gap
   between two competing rules on the same property */
@keyframes box-flag {
    0%        { outline-color: transparent; }
    13%       { outline-color: rgba(247, 241, 236, .26); }
    72%       { outline-color: rgba(247, 241, 236, .26); }
    86%, 100% { outline-color: var(--bone); }
}

@keyframes pop  { from { opacity: 0; transform: scale(.9); } to { opacity: 1; transform: scale(1); } }
@keyframes stamp { from { opacity: 0; } to { opacity: 1; } }
@keyframes fade-back { to { opacity: .14; } }

/* ── detection layers ────────────────────────────────────── */

.layers { background: var(--void); }
.layers .band-head,
.layer-list,
.privacy-grid,
.setup-grid,
.privacy .band-head { max-width: var(--measure); margin-inline: auto; }

.layer-list {
    list-style: none;
    padding: 0;
    margin-inline: auto;
    margin-block: 0;
    border-top: 1px solid var(--bone-16);
}

.layer {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr) minmax(0, 21rem);
    gap: 1.5rem clamp(1.5rem, 3vw, 3rem);
    padding: 2.1rem 0;
    border-bottom: 1px solid var(--bone-16);
    align-items: start;
}

/* the outcome line below supplies the closing rule */
.layer-list .layer:last-child { border-bottom: 0; }

.layer .tag { padding-top: .55rem; }

.layer-body h3 {
    font-family: var(--display);
    font-weight: 700;
    font-stretch: 88%;
    font-size: 1.35rem;
    line-height: 1.15;
    margin: 0 0 .55rem;
    letter-spacing: .005em;
}

.layer-body p {
    margin: 0;
    color: var(--bone-70);
    max-width: 46rem;
}

/* the differentiator gets the weight — structure carrying meaning */
.layer-lead {
    background: linear-gradient(100deg, rgba(231, 23, 57, .16), rgba(231, 23, 57, 0) 72%);
    padding-inline: 1.4rem;
    margin-inline: -1.4rem;
}
.layer-lead .tag { color: var(--bone); }
.layer-lead .layer-body h3 { font-size: clamp(1.6rem, 1.2rem + 1.2vw, 2.1rem); }
.layer-lead .layer-body p { color: var(--bone); }

/* ── exhibits ────────────────────────────────────────────────
   Each layer shows its mechanism instead of only asserting it. These are
   illustrations, drawn in CSS and one inline SVG — no figure here is read
   from a live server, and the QR glyph is decorative, not a scannable code.
   ──────────────────────────────────────────────────────────── */

.exhibit {
    font-family: var(--mono);
    font-size: .74rem;
    line-height: 1.45;
    border: 1px solid var(--bone-16);
    padding: .9rem 1rem 1rem;
    background: rgba(0, 0, 0, .22);
}

.ex-note {
    margin: .8rem 0 0;
    padding-top: .7rem;
    border-top: 1px solid var(--bone-16);
    color: var(--bone-42);
    font-size: .7rem;
}

/* OCR — what a link filter sees, versus what is actually there */
.ex-fields { margin: 0; display: grid; gap: .3rem; }
.ex-fields > div {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
}
.ex-fields dt { color: var(--bone-42); }
.ex-fields dd { margin: 0; color: var(--bone-70); white-space: nowrap; }
.ex-nil { color: var(--bone-42); }

.ex-hit {
    margin-top: .35rem;
    padding-top: .5rem;
    border-top: 1px solid var(--bone-16);
}
.ex-hit dt { color: var(--bone); }
.ex-hit dd { color: var(--bone); font-weight: 600; }

/* image hash — same picture, different file */
.ex-hash {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
    gap: .7rem;
    align-items: center;
}
.ex-hash figure { margin: 0; }
.ex-hash figcaption {
    margin-top: .4rem;
    color: var(--bone-42);
    font-size: .64rem;
    line-height: 1.3;
    /* both captions reserve two lines so the two frames stay level */
    min-height: 2.6em;
}
.ex-rel { margin: 0; color: var(--bone); font-size: 1.1rem; align-self: center; }

.ex-thumb {
    aspect-ratio: 4 / 3;
    border: 1px solid var(--bone-16);
    background: var(--void);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: .28rem;
    padding: .4rem;
}
.ex-thumb i { display: block; height: .28rem; background: var(--bone-42); }
.ex-thumb i:nth-child(1) { width: 55%; }
.ex-thumb i:nth-child(2) { width: 80%; background: var(--bone); height: .5rem; }
.ex-thumb i:nth-child(3) { width: 40%; }
/* the repost: cropped in and knocked about by re-encoding */
.ex-thumb.is-recrop { align-items: flex-start; padding-left: .1rem; opacity: .72; }
.ex-thumb.is-recrop i:nth-child(1) { width: 66%; }
.ex-thumb.is-recrop i:nth-child(2) { width: 96%; }
.ex-thumb.is-recrop i:nth-child(3) { width: 48%; }

/* language — the weight the classifier puts on each phrase */
.ex-tokens { list-style: none; margin: 0; padding: 0; display: grid; gap: .45rem; }
.ex-tokens li { display: grid; grid-template-columns: 1fr 4.5rem; gap: .7rem; align-items: center; }
.ex-tokens span { color: var(--bone); }
.ex-tokens i {
    display: block;
    height: .5rem;
    background: var(--bone);
    /* the bar is the value; scaleX keeps the track width honest */
    width: calc(var(--w) * 100%);
    min-width: 2px;
}
.ex-tokens .is-clean span { color: var(--bone-42); }
.ex-tokens .is-clean i { background: var(--bone-42); }

/* domain — one character apart */
.ex-domain { display: grid; gap: .35rem; }
.ex-word {
    margin: 0;
    font-size: 1rem;
    letter-spacing: .12em;
    color: var(--bone-70);
}
.ex-word.is-bad { color: var(--bone); }
.ex-word .is-diff {
    background: var(--bone);
    color: var(--field);
    padding: 0 .18em;
}
.ex-word:not(.is-bad) .is-diff { background: var(--bone-16); color: var(--bone); }

/* QR — the destination was never hidden, only encoded */
.ex-qr { display: grid; justify-items: start; gap: .55rem; }
.ex-qr svg {
    width: 4.6rem;
    height: 4.6rem;
    color: var(--bone);
    shape-rendering: crispEdges;
}
.ex-arrow { margin: 0; color: var(--bone-42); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; }
.ex-url { margin: 0; color: var(--bone); word-break: break-all; }

/* ── zero setup ──────────────────────────────────────────── */

.setup { background: var(--void-2); }

.setup-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: clamp(2.5rem, 5vw, 4.5rem);
    align-items: start;
}

.setup-copy .band-intro { margin-top: 1.3rem; }
.setup-copy strong { color: var(--bone); font-weight: 600; }

.commands { margin: 0; display: grid; gap: 1px; background: var(--bone-16); border: 1px solid var(--bone-16); }

.command { background: var(--void); padding: 1.05rem 1.2rem; }

.command dt {
    font-family: var(--mono);
    font-weight: 600;
    font-size: .92rem;
    color: var(--bone);
    margin: 0 0 .3rem;
}

.command dd {
    margin: 0;
    color: var(--bone-70);
    font-size: .95rem;
    line-height: 1.5;
}

/* ── privacy ─────────────────────────────────────────────── */

.privacy { background: var(--void); }

.privacy-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1px;
    background: var(--bone-16);
    border: 1px solid var(--bone-16);
}

.privacy-col { background: var(--void); padding: 1.6rem 1.5rem 1.8rem; }
.privacy-col p { margin: .75rem 0 0; color: var(--bone-70); }
.privacy-col-wide { grid-column: 1 / -1; }
.privacy-col-wide p { color: var(--bone); }

/* ── closer ──────────────────────────────────────────────── */

.closer {
    background: var(--field);
    text-align: center;
    position: relative;
    clip-path: polygon(0 5vw, 100% 0, 100% 100%, 0 100%);
    padding-top: calc(var(--band-y) + 5vw);
}

.closer-line {
    font-size: clamp(2.1rem, 1rem + 4.6vw, 4.2rem);
    max-width: 18ch;
    margin: 0 auto clamp(2rem, 4vw, 2.8rem);
}

.closer .microcopy { margin-inline: auto; }

/* ── footer ──────────────────────────────────────────────── */

.footer {
    background: var(--void);
    padding: 2.5rem var(--gutter);
    display: flex;
    align-items: center;
    gap: .9rem;
    justify-content: center;
    flex-wrap: wrap;
}
.footer .brand-mark { width: 26px; height: 26px; border-radius: 6px; }
.footer p {
    margin: 0;
    font-size: .85rem;
    color: var(--bone-42);
    font-family: var(--mono);
}

/* ── responsive ──────────────────────────────────────────── */

@media (max-width: 940px) {
    .hero {
        grid-template-columns: minmax(0, 1fr);
        padding-top: clamp(2rem, 6vw, 3rem);
    }
    .hero-copy { justify-self: start; max-width: 36rem; }
    .scanner { justify-self: start; max-width: 26rem; }
    .setup-grid { grid-template-columns: minmax(0, 1fr); }
    /* exhibit drops under the prose rather than squeezing beside it */
    .layer { grid-template-columns: 7.5rem minmax(0, 1fr); }
    .exhibit { grid-column: 2; max-width: 26rem; }
}

@media (max-width: 620px) {
    .masthead { padding-block: .9rem; }
    .masthead .btn-sm { display: none; }
    .layer { grid-template-columns: minmax(0, 1fr); gap: .7rem; }
    .layer .tag { padding-top: 0; }
    /* undo the tablet rule, or it forces an implicit second column here */
    .exhibit { grid-column: auto; max-width: none; margin-top: .4rem; }
    .privacy-grid { grid-template-columns: minmax(0, 1fr); }
    .scanner { max-width: none; }
    .hero { clip-path: polygon(0 0, 100% 0, 100% calc(100% - 7vw), 0 100%); }
    .closer { clip-path: polygon(0 7vw, 100% 0, 100% 100%, 0 100%); }
    .hero::after {
        clip-path: polygon(0 100%, 100% calc(100% - 7vw),
                           100% calc(100% - 8.4vw), 0 calc(100% - 1.4vw));
    }
    .closer::before { clip-path: polygon(0 7vw, 100% 0, 100% 1.4vw, 0 calc(7vw + 1.4vw)); }
}

@media (prefers-reduced-motion: reduce) {
    .js .scanner .ocr-line,
    .js .scanner .chip,
    .js .scanner .readout-note,
    .js .scanner .readout-verdict,
    .js .scanner .verdict-stamp { opacity: 1; transform: none; animation: none !important; }
    .js .ocr-region { animation: none !important; outline-color: rgba(247, 241, 236, .26); opacity: .14; }
    .js .ocr-region.is-flag { outline-color: var(--bone); opacity: 1; }
    .btn { transition: none; }
    .btn:hover, .btn:active { transform: none; }
}
