/* Full-bleed section bands. Separate from theme-2026.css so the layout change
 * can be dropped independently of the colour/type overlay.
 *
 * Bands are siblings inside a wrapper with no width limit; `.n2n-band__inner`
 * re-applies the 786px measure. Does not use the `100vw` negative-margin
 * breakout, which overflows horizontally wherever a scrollbar takes layout
 * width.
 *
 * `.content` is untouched - 19 templates use it, including admin pages.
 */

/* style.css sets no global border-box, so `width: 100%` plus padding overflows
 * the viewport (the band measured 532px inside a 500px viewport before this). */
.n2n-bands,
.n2n-bands *,
.n2n-bands *::before,
.n2n-bands *::after {
    box-sizing: border-box;
}

.n2n-bands {
    display: flex;
    flex-direction: column;
    width: 100%;
    flex-grow: 1;
}

/* The wrapper grows to push the footer down, but the bands inside it don't - so
 * on a short page the leftover space showed the cream page background as a
 * strip between the last band and the footer. Let the last band absorb it. */
.n2n-bands > .n2n-band:last-child {
    flex-grow: 1;
}

/* `.dashboard-content` carries `padding-bottom: 32px` from the old `.content`
 * column. In a band layout that sits below the last band and shows 32px of page
 * background above the footer. flex-grow can't absorb padding. */
.n2n-bands.dashboard-content {
    padding-bottom: 0;
}

.n2n-band {
    width: 100%;
    padding: clamp(26px, 3.2vw, 44px) clamp(16px, 4vw, 32px);
}

/* Re-applies the measure that `.content` used to provide, plus the column flow
 * its children were written against (`align-items: flex-start`). */
.n2n-band__inner {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    max-width: 786px;
    margin: 0 auto;
}

.n2n-band--cream {
    background-color: var(--n2n-cream);
}

.n2n-band--tint {
    background-color: var(--n2n-tint);
}

/* Hero band. Halftone dots are a CSS gradient rather than the deck's 65KB
 * JPEG - the pattern is regular, so this costs nothing and stays sharp. */
.n2n-band--navy {
    position: relative;
    background-color: var(--n2n-band-blue);
    color: var(--n2n-cream);
}

/* Dots fade in diagonally, so the top of the band is flat where it meets the
 * flat header and no seam shows. */
.n2n-band--navy::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        radial-gradient(rgba(255, 255, 255, 0.13) 1.1px, transparent 1.5px);
    background-size: 7px 7px;
    -webkit-mask-image: linear-gradient(to top left, #000 5%, transparent 68%);
    mask-image: linear-gradient(to top left, #000 5%, transparent 68%);
}

/* Keep content above the texture layer. */
.n2n-band--navy > .n2n-band__inner {
    position: relative;
    z-index: 1;
}

/* Navy paper band. The grain is a 256px tile, high-passed to a uniform mean so
 * the repeat has no visible seam grid - 8KB rather than 120KB for a full-width
 * image. background-color stays set so a 404 leaves the right colour. */
.n2n-band--slate {
    position: relative;
    /* Official artwork: navy line-art city with the houses along the bottom.
     * One asset now does what a tiled paper texture plus a separate street
     * layer used to. `bottom center` anchors the houses to the foot of the band
     * whatever its height; the city fills upward behind the content.
     *
     * background-color is the artwork's own navy, so a failed fetch or an
     * uncovered edge still reads as the right field.
     *
     * image-set gives WebP to browsers that take it (75KB) and JPEG to those
     * that don't (127KB). */
    background-color: #022c60;
    background-image: image-set(
        url("assets/textures/band-houses-navy.webp") type("image/webp"),
        url("assets/textures/band-houses-navy.jpg") type("image/jpeg")
    );
    background-image: -webkit-image-set(
        url("assets/textures/band-houses-navy.webp") type("image/webp"),
        url("assets/textures/band-houses-navy.jpg") type("image/jpeg")
    );
    background-repeat: no-repeat;
    background-position: bottom center;
    background-size: cover;
    color: var(--n2n-cream);
    overflow: hidden;
}

/* The houses are part of the band background now, so the old separate street
 * layer is gone. `::after` stays available for bands that want to suppress or
 * add something of their own. */

/* Slightly less than the street's height, so the lowest cards overlap the
 * rooflines rather than sitting clear of them. */
.n2n-band--slate {
    padding-bottom: clamp(120px, 15vw, 250px);
}

/* Content sits above the illustration. */
.n2n-band--slate > .n2n-band__inner {
    position: relative;
    z-index: 1;
}

body.theme-2026 .n2n-band--slate .dashboard-kicker,
body.theme-2026 .n2n-band--slate .dashboard-section-title {
    color: var(--n2n-cream);
}

/* ...but not inside a paper sheet. A light panel laid on a dark band flips the
 * ink back: cream headings on cream paper rendered invisible when the slate
 * band moved down to hold the paper sheets. */
body.theme-2026 .n2n-band--slate .dashboard-paper .dashboard-kicker,
body.theme-2026 .n2n-band--slate .dashboard-paper .dashboard-section-title,
body.theme-2026 .n2n-band--slate .dashboard-paper p,
body.theme-2026 .n2n-band--slate .dashboard-paper a {
    color: var(--n2n-navy);
}

body.theme-2026 .n2n-band--slate .dashboard-paper .dashboard-section-hr path {
    stroke: rgba(0, 33, 62, 0.45);
}

body.theme-2026 .n2n-band--slate .dashboard-section-hr path {
    stroke: rgba(255, 251, 239, 0.4);
}

/* ---------- One large paper sheet
 * Creased sheet with CSS staples on a colour field. One per section, not per
 * card. */
.dashboard-paper {
    position: relative;
    width: 100%;
    background-color: var(--n2n-cream);
    /* Official crumpled grid paper, faded 70% toward the cream. At full strength
     * the grid lines measure 59 levels of contrast, which is fine behind three
     * lines of copy and unreadable behind the script - a volunteer reads that
     * one at a door. Faded to 19 levels it still reads as gridded paper up
     * close without competing with text. */
    background-image: image-set(
        url("assets/textures/grid-white.webp") type("image/webp"),
        url("assets/textures/grid-white.jpg") type("image/jpeg"));
    background-size: cover;
    background-position: center;
    border-radius: 4px;
    padding: clamp(28px, 4vw, 52px) clamp(24px, 4vw, 56px) clamp(30px, 4vw, 52px);
    box-shadow: 0 10px 30px rgba(0, 33, 62, 0.18);
}

.dashboard-paper::before,
.dashboard-paper::after {
    content: "";
    position: absolute;
    top: 15px;
    width: 34px;
    height: 4px;
    border-radius: 1px;
    background: linear-gradient(to bottom, #6e7683 0%, #aab1bb 38%, #e8ebef 55%, #8d949f 100%);
    box-shadow: 0 1px 2px rgba(0, 33, 62, 0.28);
    transform: rotate(-1.2deg);
}

/* Second sheet in the same band needs air between the two. */
.dashboard-paper--stacked {
    margin-top: clamp(20px, 2.4vw, 34px);
}

.dashboard-paper::before { left: 8%; }
.dashboard-paper::after  { right: 8%; transform: rotate(1deg); }

/* Brand deck's yellow neighbourhood paper. Only the margins around the panels
 * show it, so it never sits behind body text. */
.n2n-band--yellow {
    background-color: var(--n2n-yellow-deep);
    background-image: url("assets/textures/band-yellow-neighborhood.jpg");
    background-size: cover;
    background-position: center;
    color: var(--n2n-navy);
}

/* The hero carries the page's identity, so it gets a wider measure and much
 * bigger type than the reading columns below it. At 786px inside a 1400px band
 * the content stranded itself in the left third and the band read as empty. */
.n2n-band--hero .n2n-band__inner {
    max-width: 1100px;
}

/* The one colour break on the page is hero -> Resources, so the yellow accent
 * moves there from under the header, where it was cutting a seam through a
 * field meant to read as continuous. */
.n2n-band--hero {
    border-bottom: 4px solid var(--n2n-yellow);
}

/* Trimmed from ~790px: a full-height hero pushed Resources below the fold on a
 * laptop, so nothing actionable was visible without scrolling. */
.n2n-band--hero {
    padding-top: clamp(26px, 3vw, 40px);
    padding-bottom: clamp(26px, 3vw, 40px);
}

/* ---------- Hero art
 * Hidden below 900px. The frame must be hidden too, not just the image - it
 * carries its own background and would paint an empty rectangle. */
.dashboard-hero-art,
.dashboard-hero-art-frame {
    display: none;
}

.dashboard-hero-copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    width: 100%;
    min-width: 0;
}

@media (min-width: 900px) {
    /* Two columns via flex rather than grid: the copy is one stack, the art is
     * one item beside it. Grid put each flat child on its own row and spread
     * them down the band to match the art's height. */
    body.theme-2026 .n2n-band--hero .n2n-band__inner {
        flex-direction: row;
        align-items: center;
        gap: clamp(32px, 5vw, 72px);
    }

    body.theme-2026 .n2n-band--hero .dashboard-hero-copy {
        flex: 1 1 auto;
    }

    /* Torn cyan-paper sheet behind the photo - the deck's crumpled light-blue
     * stock (#96e2e6, nearest palette value Light Blue Tint 3 #A6F2F6).
     *
     * If the photo is ever recropped or replaced: the sheet and the photo's cyan
     * speech bubble differ by only 1.13:1. They read as separate shapes only
     * because white grid paper sits between them. A cyan element against this
     * edge will fuse with the frame.
     *
     * drop-shadow, not box-shadow, so the shadow follows the torn silhouette. */
    body.theme-2026 .n2n-band--hero .dashboard-hero-art-frame {
        display: block;
        position: relative;
        flex: 0 0 clamp(290px, 30vw, 410px);
        width: clamp(290px, 30vw, 410px);
        /* style.css sets no global border-box, so without this the padding is
         * added to the width and the frame overflows its column. */
        box-sizing: border-box;
        padding: 16px;
        /* White grid, not cyan. The official photo carries its own cyan grid
         * background (#B3E6E9); a cyan frame at #96E2E6 would be within ~1.1:1
         * of it and the two would read as one shape. White reads as the photo
         * being a cyan sheet laid on a white one. */
        background-color: #fffbef;
        background-image: image-set(
            url("assets/textures/grid-white.webp") type("image/webp"),
            url("assets/textures/grid-white.jpg") type("image/jpeg"));
        background-size: cover;
        transform: rotate(-2.2deg);
        filter: drop-shadow(0 14px 30px rgba(0, 0, 0, 0.42));
    }

    /* Torn edge. Guarded per the mask rule elsewhere in this theme: an
     * unsupported mask leaves a plain cream rectangle, which is a fine sheet -
     * an unguarded mask would render the whole frame invisible. */
    @supports ((-webkit-mask-image: url("assets/textures/torn-photo-mask.png")) or
               (mask-image: url("assets/textures/torn-photo-mask.png"))) {
        body.theme-2026 .n2n-band--hero .dashboard-hero-art-frame {
            -webkit-mask-image: url("assets/textures/torn-photo-mask.png");
            mask-image: url("assets/textures/torn-photo-mask.png");
            -webkit-mask-size: 100% 100%;
            mask-size: 100% 100%;
            -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
        }
    }

    body.theme-2026 .n2n-band--hero .dashboard-hero-art {
        display: block;
        width: 100%;
        height: auto;
    }

    /* Stats sit beside the message inside the copy stack. */
    body.theme-2026 .n2n-band--hero .dashboard-welcome-card > .button {
        justify-self: start;
        width: auto;
    }
}

/* Hierarchy swap without a markup change: `.dashboard-title` ("Dashboard", a
 * nav label) becomes the small kicker, and `.dashboard-welcome-greeting` is
 * promoted to the headline. */
body.theme-2026 .n2n-band--hero .dashboard-title {
    font-family: var(--n2n-font-kicker);
    font-size: clamp(20px, 2.1vw, 28px);
    font-weight: 400;
    line-height: 1.1;
    letter-spacing: 0.02em;
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

/* 76px was manifesto scale for what is, in the end, a greeting - it wrapped to
 * two lines and cost ~190px of height on its own. The reference earns that size
 * because its headline carries an argument; ours says hello. */
body.theme-2026 .n2n-band--hero .dashboard-welcome-greeting {
    font-family: var(--n2n-font-heading);
    font-size: clamp(30px, 3.6vw, 46px);
    font-weight: 700;
    line-height: 1.02;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 14px;
    max-width: 22ch;
}

/* The rule spanned ~95% of the viewport while the text below it stopped at
 * ~45%, so it underlined empty space and made the band look emptier. Section
 * rules still earn their place in the light bands below. */
body.theme-2026 .n2n-band--hero .dashboard-section-hr {
    display: none;
}

/* ---------- Highlighted headline
 * The yellow band's line-art is busy behind text, so the heading needs an
 * opaque ground. Each line is `width: fit-content` so the cream hugs its own
 * text and the pair reads as two highlighted lines, not a panel.
 *
 * Line-heights are tightened: the kicker ships at 1.5, which left ~19px of dead
 * cream around 25px of type and merged the two bars into one mass. */
.n2n-band--yellow .dashboard-headline {
    position: relative;
    display: inline-block;
    padding: 0;
    margin-bottom: 6px;
}

.n2n-band--yellow .dashboard-kicker,
.n2n-band--yellow .dashboard-section-title {
    width: fit-content;
    background: var(--n2n-cream);
    border-radius: 2px;
}

.n2n-band--yellow .dashboard-kicker {
    line-height: 1.02;
    padding: 2px 8px;
    /* separates the two highlights; the title ships with margin-top: -4px,
     * which is what made them overlap by 2px */
    margin: 0 0 9px;
}

.n2n-band--yellow .dashboard-section-title {
    line-height: 0.98;
    padding: 2px 8px;
    margin: 0;
}

.n2n-band--yellow .dashboard-headline > * {
    position: relative;
    z-index: 1;
}

/* Section kicker. This face is only ever the small label above a heading,
 * never the heading itself. */
body.theme-2026 .dashboard-kicker {
    font-family: var(--n2n-font-kicker);
    font-size: clamp(19px, 2vw, 25px);
    font-weight: 400;
    letter-spacing: 0.02em;
    color: var(--n2n-navy);
    /* Matches the hero's kicker margin exactly, so kicker-to-heading spacing is
     * identical in both places. */
    margin: 0 0 2px;
}

/* `.dashboard-section-title` ships with `margin: 16px 0 0 0`, which pushed the
 * heading 16px clear of its kicker - the hero pair has no top margin at all, so
 * the two sat at visibly different distances. */
body.theme-2026 .dashboard-kicker + .dashboard-section-title {
    /* -4px, not 0: zeroing the margin still left a 17px optical gap against the
     * hero's 13px, because the section heading is a smaller size with a
     * different line-height. */
    margin-top: -4px;
}

/* Full-strength navy on yellow. At 72% opacity it read as a caption rather than
 * the eyebrow the hero's kicker is - the hero version carries full contrast
 * (yellow on navy), so this needs to match that weight. */
body.theme-2026 .n2n-band--yellow .dashboard-kicker {
    color: var(--n2n-navy);
    opacity: 1;
}

/* The yellow dash and the kicker are two eyebrows doing one job. */
body.theme-2026 .dashboard-section-title::before {
    display: none;
}

/* ---------- Hero stats
 * The two numbers are the most scannable, most motivating content on a
 * canvasser's dashboard, and they were buried mid-sentence at body size. */

.dashboard-stats {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(24px, 3.5vw, 48px);
    margin: 0 0 18px;
}

.dashboard-stat__num {
    display: block;
    font-family: var(--n2n-font-heading);
    font-weight: 700;
    font-size: clamp(38px, 4.2vw, 54px);
    line-height: 0.9;
    color: var(--n2n-yellow);
}

.dashboard-stat__label {
    display: block;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 13px;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 251, 239, 0.75);
    margin-top: 6px;
}

/* Tighter rhythm: the greeting, stats and CTA read as one block instead of
 * four items drifting apart down a tall band. */
body.theme-2026 .n2n-band--hero .dashboard-welcome-text,
body.theme-2026 .n2n-band--hero .dashboard-welcome-subtext {
    margin: 0 0 14px;
    max-width: 56ch;
    font-size: 17px;
}

body.theme-2026 .n2n-band--hero .dashboard-cta-button {
    margin-top: 4px;
}

/* Yellow band: navy ink, and the section rule needs to read on yellow rather
 * than on cream. */
body.theme-2026 .n2n-band--yellow .dashboard-section-title,
body.theme-2026 .n2n-band--yellow .dashboard-resource-title {
    color: var(--n2n-navy);
}

body.theme-2026 .n2n-band--yellow .dashboard-section-hr path {
    stroke: rgba(0, 33, 62, 0.55);
}

/* The yellow accent flash disappears on a yellow field. */
body.theme-2026 .n2n-band--yellow .dashboard-section-title::before {
    background: var(--n2n-navy);
}

/* The `body.theme-2026` prefix is required: theme-2026.css sets these navy
 * at (0,2,1), which outranks a plain `.n2n-band--navy .x` (0,2,0) whatever the
 * file order. Without it the title renders navy-on-navy. */
body.theme-2026 .n2n-band--navy h1,
body.theme-2026 .n2n-band--navy h2,
body.theme-2026 .n2n-band--navy h3,
body.theme-2026 .n2n-band--navy p,
body.theme-2026 .n2n-band--navy strong,
body.theme-2026 .n2n-band--navy a,
body.theme-2026 .n2n-band--navy .dashboard-title,
body.theme-2026 .n2n-band--navy .dashboard-section-title,
body.theme-2026 .n2n-band--navy .dashboard-welcome-greeting,
body.theme-2026 .n2n-band--navy .dashboard-welcome-text,
body.theme-2026 .n2n-band--navy .dashboard-welcome-subtext {
    color: var(--n2n-cream);
}

/* The band now supplies the colour, so the welcome card drops its own navy
 * panel rather than stacking navy on navy. */
body.theme-2026 .n2n-band--navy .dashboard-welcome-card {
    background: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    width: 100%;
}

/* Section rules read as a dark hairline on cream but disappear on navy. */
body.theme-2026 .n2n-band--navy .dashboard-section-hr path {
    stroke: rgba(255, 251, 239, 0.45);
}

/* The yellow accent flash sits above headings on light bands; on navy the
 * heading is already the loudest thing, so it would just add noise. */
body.theme-2026 .n2n-band--navy .dashboard-section-title::before {
    display: none;
}

/* `align-items: flex-start` (inherited from how `.content` laid these out) lets
 * children size to their content instead of filling the measure, which pushes
 * wide children past the band on narrow screens. Restore the stretch. */
.n2n-band__inner > * {
    width: 100%;
    max-width: 100%;
}

/* ...but not buttons. Stretching them to the full measure looks wrong at any
 * width, and with the torn-edge mask applied it smears the ragged edge across
 * ~900px so the button reads as a broken bar. */
/* The torn strip has to hug its text - stretched to the full measure it reads
 * as a white bar rather than a torn scrap. Same exception the buttons need. */
.n2n-band__inner > .dashboard-headline,
.n2n-band__inner > .button,
.n2n-band__inner > .submit-button,
.n2n-band__inner > a.button {
    width: auto;
    max-width: 100%;
    align-self: flex-start;
}

@media (max-width: 700px) {
    .n2n-band {
        padding-left: 16px;
        padding-right: 16px;
    }

    /* The resources grid is hardcoded to two columns at every width, with no
     * breakpoint to collapse it - at 390px the cards run off the screen.
     * Scoped to bands so only the dashboard is affected. */
    .n2n-band .dashboard-resources-grid {
        grid-template-columns: 1fr;
    }
}

/* ---------- Light paper band
 * The deck's white neighbourhood line-art paper, faded 38% toward the theme
 * cream and warmed to match the palette. Faint enough to run behind a full list
 * of cards.
 *
 * background-color first, so a 404 leaves the right colour. */
.n2n-band--paper {
    position: relative;
    background-color: var(--n2n-cream);
    color: var(--n2n-navy);
}

/* The texture is a layer, not the band's own background, so it can be pinned to
 * the band's WIDTH.
 *
 * Do NOT use `background-size: cover` here. The art is 960x540 and cover fills
 * both axes, so on a ~1400px-tall band it scaled to 2489x1400 - 2.6x its drawn
 * size and soft, and worse the taller the band. `100% auto` keeps the drawing
 * the same size on every page regardless of content length.
 *
 * It repeats vertically. The tile is not seamless, but the art is faint (values
 * 231-254 on cream, uniform mean) so the join has no brightness step - measured
 * at 1.18/255 against a row-to-row noise floor of 2.28. Width is pinned to
 * 100%, so there is never a join down the side. */
.n2n-band--paper::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: url("assets/textures/band-cyan-neighborhood.jpg");
    background-repeat: repeat;
    background-position: top center;
    background-size: 100% auto;
}

/* Content above the texture layer. */
.n2n-band--paper > .n2n-band__inner {
    position: relative;
    z-index: 1;
}

/* ---------- Neighbors page
 * Three bands, as on the dashboard: navy hero, light band for the list, navy
 * paper band with the street closing into the footer.
 */

/* `.page` is `display: flex; justify-content: space-between; height: 100%`, so
 * a middle child that doesn't grow leaves the leftover viewport height split
 * above and below it as bare page background. `.neighbors-page` also carries
 * `.n2n-bands` in the template; this re-states the grow in case that is
 * dropped. */
body.theme-2026 .neighbors-page {
    flex-grow: 1;
}

/* Same bug, same fix, on the page this list links straight into: the neighbor
 * detail form sat vertically centred in the viewport with a band of bare cream
 * above and below it. Nothing else about that page is changed here. */
body.theme-2026 .neighbor-detail {
    flex-grow: 1;
}

/* Must stay BELOW the navy-band ink block: `body.theme-2026 .n2n-band--navy p`
 * is (0,2,2) and would otherwise paint the kicker cream. These match that
 * specificity and win on source order. */
body.theme-2026 p.neighbors-hero__kicker {
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

body.theme-2026 h1.neighbors-hero__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(32px, 4vw, 52px);
    font-weight: 700;
    line-height: 1.0;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 18px;
}

body.theme-2026 p.neighbors-hero__status {
    color: rgba(255, 251, 239, 0.86);
    font-size: 16px;
    line-height: 1.5;
    max-width: 46ch;
    margin: 0 0 4px;
}

body.theme-2026 .neighbors-hero__cta {
    margin-top: 14px;
}

/* The two stats say "2 done, 3 left"; the bar says "nearly there" without
 * being read. One shape is faster than two numbers for the only question the
 * canvasser is asking mid-shift. */
.neighbors-progress {
    width: 100%;
    max-width: 380px;
    height: 10px;
    margin: 0 0 18px;
    border-radius: 999px;
    background: rgba(255, 251, 239, 0.2);
    overflow: hidden;
}

.neighbors-progress__fill {
    display: block;
    height: 100%;
    min-width: 0;
    border-radius: 999px;
    background: var(--n2n-yellow);
}

.neighbors-hero .dashboard-stats {
    margin-bottom: 16px;
}

/* ---------- The map, framed
 *
 * Same light-blue paper frame the dashboard gives its photo, which caps a map
 * that previously ran the full viewport width at 300-400px tall.
 *
 * No rotation and no torn mask here: the map is interactive, and the mask bites
 * into the corner where Leaflet puts its zoom controls. */
.neighbors-map-frame {
    position: relative;
    width: 100%;
    box-sizing: border-box;
    padding: 12px;
    margin-top: 26px;
    border-radius: 3px;
    /* colour first so a failed texture fetch still gives the right sheet */
    background-color: #96e2e6;
    background-image: url("assets/textures/band-cyan-paper.jpg");
    background-size: cover;
    box-shadow: 0 14px 30px rgba(0, 0, 0, 0.42);
}

.neighbors-map-frame .neighbors-map {
    width: 100%;
    height: 240px;
    margin: 0;
}

/* The navy-band rule above paints every link cream, and the zoom control's "+"
 * and "-" are links on a white button - they rendered as blank squares. Needs
 * the band class to out-specify (0,2,2). */
body.theme-2026 .n2n-band--navy .neighbors-map-frame .leaflet-control-zoom a {
    color: var(--n2n-navy);
    background: #ffffff;
}

body.theme-2026 .n2n-band--navy .neighbors-map-frame .leaflet-control-zoom a:hover {
    color: var(--n2n-navy);
    background: var(--n2n-tint);
}

/* Same problem, same fix: the OpenStreetMap attribution is a link. */
body.theme-2026 .n2n-band--navy .neighbors-map-frame .leaflet-control-attribution a {
    color: #2f5c88;
}

/* "You are here" - smaller and a different shape from the numbered door pins. */
.neighbors-map-pin--you {
    display: block;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background: var(--n2n-cyan);
    border: 3px solid #ffffff;
    box-shadow: 0 0 0 2px var(--n2n-navy), 0 2px 5px rgba(0, 22, 42, 0.4);
}

@media (min-width: 900px) {
    /* Beside the copy, matching the footprint of the dashboard's hero art so
       the two heroes have the same proportions. */
    body.theme-2026 .n2n-band--hero .neighbors-map-frame {
        flex: 0 0 clamp(320px, 33vw, 460px);
        width: clamp(320px, 33vw, 460px);
        margin-top: 0;
    }

    body.theme-2026 .n2n-band--hero .neighbors-map-frame .neighbors-map {
        height: clamp(260px, 25vw, 330px);
    }
}

/* ---------- List band */

.neighbors-list-band .n2n-band__inner {
    /* Wider than the 786px reading measure: this band holds a two-up card grid,
       not a column of prose, and at 786px the cards were narrower than their
       own addresses. Matches the hero above it so the two bands line up. */
    max-width: 1100px;
}

/* Kicker over heading, left-aligned, matching the dashboard. The heading block
 * used to be centred while the accent above it sat left, so the two disagreed
 * and the accent read as a stray mark. */
body.theme-2026 .neighbors-list-header {
    text-align: left;
    padding: 0;
    margin-bottom: 18px;
}

body.theme-2026 .neighbors-list-header .dashboard-kicker {
    margin: 0 0 2px;
}

/* `.lists-nav` ships centred at `min-width: 60%` with a 32px top margin. Sized
 * as the small control it is and pinned to the band's left edge. */
body.theme-2026 .neighbors-lists-nav {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 12px;
    min-width: 0;
    max-width: none;
    margin: 0 0 18px;
    padding: 0;
}

body.theme-2026 .neighbors-lists-nav .lists-nav__lists-bar {
    gap: 8px;
}

body.theme-2026 .neighbors-lists-nav .lists-nav__link {
    width: 32px;
    height: 32px;
    border-radius: 3px;
    border: 2px solid var(--n2n-navy);
    background: var(--n2n-cream);
    color: var(--n2n-navy);
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 15px;
}

body.theme-2026 .neighbors-lists-nav .lists-nav__link:hover {
    border-color: var(--n2n-navy);
    background: var(--n2n-tint);
    color: var(--n2n-navy);
}

body.theme-2026 .neighbors-lists-nav .lists-nav__link--current,
body.theme-2026 .neighbors-lists-nav .lists-nav__link--current:hover {
    border-color: var(--n2n-navy);
    background: var(--n2n-navy);
    color: var(--n2n-cream);
}

body.theme-2026 .neighbors-lists-nav .lists-nav__arrow {
    font-size: 26px;
    line-height: 1;
    margin: 0;
}

/* ---------- Closing band
 *
 * The dashboard's navy paper band and street, reused.
 *
 * min-height is required: the street is an absolutely-positioned layer in a
 * band with `overflow: hidden`, and this band is usually empty (the
 * return-assignments panel only renders in two states). Without it the band
 * collapses below the artwork height and crops the rooflines flat. */
.neighbors-closing-band {
    min-height: clamp(190px, 25vw, 380px);
    /* `.n2n-bands > .n2n-band:last-child` doesn't reach this band - the partial
     * ends with the map scripts and the achievements data div, so this is not
     * the wrapper's last child. */
    flex-grow: 1;
}

/* Same measure as the two bands above it, so the sheet starts on the page's one
 * left edge. At the narrower 786px default the band's content began ~175px
 * inboard of everything else on the page. */
.neighbors-closing-band .n2n-band__inner {
    max-width: 1100px;
}

.neighbors-closing-band .dashboard-paper {
    max-width: 640px;
}

/* Returning your list is a way out, not the thing the page wants you to do, so
 * it takes the same quiet navy the dashboard's secondary buttons take rather
 * than the primary red. */
body.theme-2026 .neighbors-return-button {
    background-color: var(--n2n-navy);
    color: var(--n2n-cream);
    margin-top: 6px;
}

body.theme-2026 .neighbors-return-button:hover {
    background-color: var(--n2n-navy-mid);
    color: var(--n2n-cream);
}

/* Links inside a paper sheet get their ink flipped to navy by the slate-band
 * rules above, which also costs them the only other thing marking them as
 * links. */
body.theme-2026 .neighbors-return-paper a {
    text-decoration: underline;
    font-weight: 600;
}

/* ---------- Simple page head
 *
 * Script, Printouts, Contact, Achievements. Same navy masthead as the
 * dashboard and neighbors heroes, minus the art and the wide measure - these
 * are reading pages, so the head sits on the same 786px column as the text
 * below it. The yellow rule is repeated from `.n2n-band--hero` rather than
 * factored out. */
.n2n-band--pagehead {
    border-bottom: 4px solid var(--n2n-yellow);
    padding-top: clamp(24px, 3vw, 40px);
    padding-bottom: clamp(26px, 3.2vw, 42px);
}

/* Must out-specify `body.theme-2026 .n2n-band--navy p` (0,2,2), which would
 * otherwise paint the kicker cream along with the rest of the band. */
body.theme-2026 p.n2n-pagehead__kicker {
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

body.theme-2026 h1.n2n-pagehead__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(32px, 4vw, 48px);
    font-weight: 700;
    line-height: 1.0;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 14px;
}

body.theme-2026 p.n2n-pagehead__sub {
    color: rgba(255, 251, 239, 0.86);
    font-size: 17px;
    line-height: 1.55;
    max-width: 58ch;
    margin: 0;
}

/* ---------- Simple page body band */

/* `.page` is `justify-content: space-between` with a fixed height, so leftover
 * viewport height is split above and below a middle child that doesn't grow.
 * These pages are short, so the body band absorbs it. */
.n2n-page-band {
    flex-grow: 1;
    padding-bottom: clamp(36px, 4.5vw, 64px);
}

/* One measure for the whole page, head included. */
.n2n-page-band .n2n-band__inner {
    max-width: 786px;
}

.n2n-page-cta {
    margin-top: clamp(22px, 2.6vw, 34px);
}

/* Secondary here: on the printouts page the printout itself is the errand, so
 * the way onward shouldn't compete with it in red. */
body.theme-2026 .n2n-page-cta--quiet {
    background-color: var(--n2n-navy);
    color: var(--n2n-cream);
}

body.theme-2026 .n2n-page-cta--quiet:hover {
    background-color: var(--n2n-navy-mid);
    color: var(--n2n-cream);
}

/* ---------- Script sheet */

body.theme-2026 .n2n-script-text {
    /* The script is stored with real line breaks between its branches; without
     * pre-wrap they collapse into one paragraph. The neighbor detail page has
     * always set this. */
    white-space: pre-wrap;
    font-family: var(--n2n-font-body);
    /* Larger than body copy: read off a phone at arm's length, mid-conversation. */
    font-size: 18px;
    line-height: 1.65;
    color: var(--n2n-navy);
    margin: 0;
}

/* Sheet sized to the measure rather than insetting the text - capping the text
 * alone left ~150px of bare paper down the right side. 680px minus padding
 * lands lines at ~62 characters. */
.n2n-script-paper {
    max-width: 680px;
}

/* Required: nothing else in the theme sets a link colour on a light band, so
 * the "no script was found" fallback rendered its mailto in browser-default
 * blue. */
body.theme-2026 .n2n-script-text a {
    color: var(--n2n-navy-mid);
    text-decoration: underline;
    font-weight: 600;
}

/* ---------- Printout card
 * Wide, with the icon beside the text rather than stacked above it - there is
 * only ever one of these, so it is not a grid card. */
.n2n-printout-card {
    display: flex;
    align-items: flex-start;
    /* Not the full measure: stretched to 786px the card put ~380px of empty
     * cream to the right of its own button. */
    max-width: 560px;
    gap: clamp(18px, 2.4vw, 28px);
    width: 100%;
    padding: clamp(22px, 3vw, 32px) clamp(22px, 3vw, 34px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    /* Same accent foot the dashboard's resource cards carry, in the red that
     * marks the primary action on the page. */
    border-bottom: 6px solid var(--n2n-red);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.18);
}

.n2n-printout-card__icon {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    max-width: 64px;
}

.n2n-printout-card__body {
    min-width: 0;
}

body.theme-2026 .n2n-printout-card__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(22px, 2.2vw, 28px);
    line-height: 1.08;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .n2n-printout-card__title::before {
    display: none;
}

body.theme-2026 .n2n-printout-card__meta {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 7px 0 0;
}

.n2n-printout-card__button {
    margin-top: 18px;
}

@media (max-width: 560px) {
    /* The icon beside the text leaves too little room for the button label at
       phone widths, so it moves above. */
    .n2n-printout-card {
        flex-direction: column;
        gap: 16px;
    }
}

/* Second paragraph in the page head, set apart from the first. */
body.theme-2026 p.n2n-pagehead__note {
    margin-top: 12px;
    padding-left: 14px;
    border-left: 3px solid var(--n2n-cyan);
    font-size: 16px;
}

/* An interface label quoted inside a sentence. Set in the button face so it
 * reads as the thing on the screen rather than as emphasis - the button it
 * points at is the same family. */
.n2n-ui-label {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--n2n-yellow);
    white-space: nowrap;
}

/* ---------- Teal neighbourhood band
 *
 * The deck's third line-art paper, after the yellow and the white. Used only on
 * Canvassing Tips, which is read once before a shift and can carry a ground
 * colour of its own.
 *
 * Mean measures #15c8d4. background-color first, so a 404 leaves the right
 * colour. */
.n2n-band--teal {
    background-color: #1ad0da;
    background-image: url("assets/textures/band-teal-neighborhood.jpg");
    background-size: cover;
    background-position: center;
    color: var(--n2n-navy);
}

/* The one page head that is not navy, so it needs the yellow rule to separate
 * two light fields. */
.n2n-tips-head {
    border-bottom: 4px solid var(--n2n-yellow);
    padding-top: clamp(26px, 3.2vw, 44px);
    padding-bottom: clamp(28px, 3.4vw, 46px);
}

/* Cream highlights behind the kicker and heading, as on the yellow band - the
 * line-art is busy and navy type on it loses its edges. */
.n2n-band--teal .dashboard-headline {
    position: relative;
    display: inline-block;
    padding: 0;
    margin-bottom: 14px;
}

.n2n-band--teal .dashboard-kicker,
.n2n-band--teal .dashboard-section-title {
    width: fit-content;
    background: var(--n2n-cream);
    border-radius: 2px;
}

.n2n-band--teal .dashboard-kicker {
    line-height: 1.02;
    padding: 2px 8px;
    margin: 0 0 9px;
}

.n2n-band--teal .dashboard-section-title {
    line-height: 0.98;
    padding: 2px 8px;
    margin: 0;
}

body.theme-2026 .n2n-band--teal .dashboard-kicker,
body.theme-2026 .n2n-band--teal .dashboard-section-title {
    color: var(--n2n-navy);
    opacity: 1;
}

/* `.n2n-band__inner > * { width: 100% }` would stretch the highlight block to
 * the full measure, and a cream bar spanning the band is not a highlight. Same
 * exception the dashboard's headline needs. */
.n2n-band__inner > .n2n-tips-headline {
    width: auto;
    max-width: 100%;
    align-self: flex-start;
}

/* This page's title is the page's h1, so it runs at hero scale rather than the
 * section scale `.dashboard-section-title` normally carries. */
body.theme-2026 h1.n2n-tips-title {
    font-size: clamp(30px, 3.6vw, 44px);
}

/* Same measure as the cards below, so the heading, the intro and the tips all
 * start on one left edge - at the default 786px the head sat ~57px inboard of
 * the cards and the two bands looked misregistered. */
.n2n-tips-head .n2n-band__inner {
    max-width: 900px;
}

body.theme-2026 .n2n-tips-intro {
    color: var(--n2n-navy);
    font-size: 17px;
    line-height: 1.55;
    max-width: 62ch;
    margin: 0;
}

/* ---------- Tip groups
 * Wide stacked cards, not the dashboard's four-up grid - each group holds three
 * full sentences.
 */
.n2n-tips-band .n2n-band__inner {
    max-width: 900px;
    gap: clamp(18px, 2.2vw, 26px);
}

.n2n-tip-group {
    width: 100%;
    padding: clamp(20px, 2.6vw, 30px) clamp(20px, 2.8vw, 34px) clamp(18px, 2.4vw, 26px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.16);
}

/* One brand colour per group, as the dashboard does across its resource cards -
 * the accent is what tells you at a glance that you have moved from one group
 * to the next while scrolling past a wall of body text. */
.n2n-tip-group:nth-of-type(1) { border-bottom: 6px solid var(--n2n-accent-cyan); }
.n2n-tip-group:nth-of-type(2) { border-bottom: 6px solid var(--n2n-yellow); }
.n2n-tip-group:nth-of-type(3) { border-bottom: 6px solid var(--n2n-red); }

.n2n-tip-group__head {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
}

.n2n-tip-group__icon {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    max-width: 52px;
}

body.theme-2026 .n2n-tip-group__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(21px, 2.1vw, 26px);
    line-height: 1.05;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .n2n-tip-group__title::before {
    display: none;
}

.n2n-tip-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.n2n-tip-list li {
    position: relative;
    padding: 0 0 0 26px;
    margin: 0;
    font-family: var(--n2n-font-body);
    font-size: 16px;
    line-height: 1.6;
    color: var(--n2n-navy);
}

.n2n-tip-list li + li {
    margin-top: 12px;
    padding-top: 12px;
    /* A hairline between tips rather than more whitespace: three long sentences
     * with only a gap between them read as one paragraph that lost its way. */
    border-top: 1px solid rgba(0, 33, 62, 0.14);
}

/* The reference site marks its criteria lists with an arrow rather than a disc,
 * which is the right shape here too - each of these is an instruction. */
.n2n-tip-list li::before {
    content: "\2192";
    position: absolute;
    left: 0;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    color: var(--n2n-red);
}

.n2n-tip-list li + li::before {
    top: 12px;
}

@media (max-width: 560px) {
    .n2n-tip-group__icon {
        width: 44px;
        height: 44px;
        max-width: 44px;
    }
}

/* ---------- Contact card
 * Same shape as the printout card. The address was previously a link inside a
 * sentence. */
.n2n-contact-card {
    display: flex;
    align-items: flex-start;
    gap: clamp(18px, 2.4vw, 28px);
    width: 100%;
    max-width: 560px;
    padding: clamp(22px, 3vw, 32px) clamp(22px, 3vw, 34px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.18);
}

.n2n-contact-card__icon {
    flex: 0 0 auto;
    width: 60px;
    height: 60px;
    max-width: 60px;
}

.n2n-contact-card__body {
    min-width: 0;
}

body.theme-2026 .n2n-contact-card__label {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 0 0 4px;
}

/* The address itself is the content, so it is set at heading scale - but in the
 * body face, because an email address in condensed uppercase is harder to read
 * back to someone than it is to look at. */
body.theme-2026 .n2n-contact-card__address {
    display: inline-block;
    font-family: var(--n2n-font-body);
    font-weight: 700;
    font-size: clamp(17px, 1.8vw, 21px);
    line-height: 1.25;
    color: var(--n2n-navy);
    text-decoration: underline;
    /* Long support addresses must break rather than push the card wide. */
    overflow-wrap: anywhere;
}

body.theme-2026 .n2n-contact-card__meta {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 8px 0 0;
}

.n2n-contact-card__button {
    margin-top: 18px;
}

@media (max-width: 560px) {
    .n2n-contact-card {
        flex-direction: column;
        gap: 16px;
    }
}

/* ---------- Achievements
 * Twelve tiles in one column ran to ~3000px. The count leads in the head, the
 * campaign goal gets its own band, and the tiles are a grid.
 */

.n2n-achievements-score .dashboard-stat__num {
    /* No second stat to sit beside, so it can run larger than the paired stats
     * on the dashboard and neighbors heroes. */
    font-size: clamp(46px, 5vw, 64px);
}

.n2n-score__of {
    font-size: 0.5em;
    color: rgba(255, 251, 239, 0.65);
    letter-spacing: 0.01em;
}

body.theme-2026 .n2n-achievements-head .n2n-pagehead__sub {
    margin-top: 4px;
}

/* Campaign goal band. The navy paper stock from the dashboard's closing band,
 * but with the street suppressed - a ground line belongs at the foot of a page,
 * and this one sits in the middle of it. */
.n2n-goal-band {
    padding-bottom: clamp(26px, 3.2vw, 44px);
}

/* The campaign-goal band sits mid-page, so it takes the navy field without the
 * houses - a row of rooflines belongs at the foot of a page, not between two
 * sections. (This used to suppress the separate street layer; the houses are
 * part of the band background now, so it suppresses the image instead.) */
.n2n-goal-band {
    background-image: none;
}

.n2n-goal {
    width: 100%;
}

.n2n-goal__stats {
    margin-bottom: 14px;
}

.n2n-goal__bar {
    max-width: 520px;
    margin-bottom: 10px;
}

body.theme-2026 .n2n-goal__caption {
    color: rgba(255, 251, 239, 0.85);
    font-size: 15px;
    margin: 0;
}

/* ---------- Badge grid */

.n2n-achievements-band .n2n-band__inner {
    /* Three tiles at ~270px plus gaps. */
    max-width: 900px;
}

.n2n-achievements {
    /* style.css caps `.achievements-container` at 786px and centres it, which
     * would re-narrow the grid inside the wider band. */
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    gap: clamp(28px, 3.4vw, 44px);
}

.n2n-badge-group {
    width: 100%;
}

body.theme-2026 .n2n-badge-group__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(20px, 2vw, 25px);
    line-height: 1.1;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0 0 4px;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--n2n-navy);
}

.n2n-badge-grid {
    display: grid;
    /* Explicit column counts, not auto-fill: at this measure auto-fill resolved to
     * four columns, leaving every three-badge row with a gap. `auto-fit` would
     * stretch the lone Champion badge across the full measure. */
    grid-template-columns: 1fr;
    gap: clamp(14px, 1.6vw, 20px);
    margin-top: 16px;
}

/* Centred so the artwork leads. The only centred layout in the app - every
 * other page is a task list. */
.n2n-badge {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 22px 18px 16px;
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid rgba(0, 33, 62, 0.18);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.14);
}

.n2n-badge--earned {
    border-bottom-color: #0f7a4a;
}

.n2n-badge--progress {
    border-bottom-color: var(--n2n-yellow);
}

/* Not started reads as unearned rather than as broken: same card, quieter. */
.n2n-badge--locked {
    background-color: rgba(252, 248, 238, 0.72);
    box-shadow: 0 3px 10px rgba(0, 33, 62, 0.08);
}

body.theme-2026 .n2n-badge__icon {
    width: 88px;
    height: 88px;
    max-width: 88px;
    /* style.css gives it a 16px right margin, written for the old horizontal
     * tile - in a centred one it shifts the artwork 8px off axis. */
    margin: 0 0 10px;
}

/* The unearned artwork is already drawn pale; this stops it competing with the
 * earned badges around it without washing it out completely. */
body.theme-2026 .n2n-badge--locked .n2n-badge__icon {
    opacity: 0.55;
}

.n2n-badge__body {
    flex: 1 1 auto;
    width: 100%;
}

body.theme-2026 .n2n-badge__title {
    font-family: var(--n2n-font-heading);
    font-size: 19px;
    line-height: 1.1;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0 0 5px;
}

body.theme-2026 .n2n-badge__desc {
    font-family: var(--n2n-font-body);
    font-size: 14px;
    line-height: 1.45;
    color: var(--n2n-navy-mid);
    margin: 0;
}

body.theme-2026 .n2n-badge__rewards {
    font-size: 13px;
    color: var(--n2n-navy-mid);
    margin-top: 8px;
}

/* `position: static` is required: style.css absolutely positions all three mark
 * classes at `top: 12px; right: 12px`, which in a centred tile puts the chip on
 * top of the artwork. */
body.theme-2026 .n2n-badge__status {
    position: static;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 14px 0 0;
    padding: 5px 11px 4px;
    border-radius: 999px;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    line-height: 1;
}

body.theme-2026 .n2n-badge--earned .n2n-badge__status {
    background: #e2f3ea;
    color: #0f6b41;
}

body.theme-2026 .n2n-badge--progress .n2n-badge__status {
    background: #fff1ce;
    color: #7a5200;
}

body.theme-2026 .n2n-badge--locked .n2n-badge__status {
    background: rgba(0, 33, 62, 0.07);
    color: var(--n2n-navy-mid);
}

.n2n-badge__status .completed-icon {
    width: 12px;
    height: 12px;
}

.n2n-badge-group__action {
    margin-top: 18px;
}

/* ---------- Referral block, inside the recruiting group */

.n2n-referral {
    margin-top: 20px;
    padding: 20px 22px 22px;
    background-color: var(--n2n-card);
    border-radius: 3px;
    border-left: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 4px 14px rgba(0, 33, 62, 0.12);
}

body.theme-2026 .n2n-referral__text {
    font-size: 15px;
    line-height: 1.5;
    color: var(--n2n-navy);
    margin: 0 0 6px;
}

body.theme-2026 .n2n-referral__link {
    display: inline-block;
    font-family: var(--n2n-font-body);
    font-weight: 600;
    font-size: 15px;
    color: var(--n2n-navy-mid);
    text-decoration: underline;
    overflow-wrap: anywhere;
}

.n2n-referral .n2n-badge-group__action {
    margin-top: 14px;
}


@media (min-width: 560px) {
    .n2n-badge-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 900px) {
    .n2n-badge-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ---------- Home page (/)
 *
 * The front door. Its job is the "email me my dashboard link" form, but it also
 * has to explain the program to anyone arriving cold, so it takes the same band
 * structure as the canvasser pages: navy hero, the form on paper, three steps,
 * houses closing into the footer.
 */

body.theme-2026.home-body .page {
    height: auto;
    min-height: 100%;
}

.home-hero .n2n-band__inner {
    max-width: 1100px;
}

body.theme-2026 p.home-hero__kicker {
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

body.theme-2026 h1.home-hero__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(34px, 4.4vw, 56px);
    font-weight: 700;
    line-height: 1.0;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 16px;
}

body.theme-2026 p.home-hero__lede {
    color: rgba(255, 251, 239, 0.86);
    font-size: 17px;
    line-height: 1.55;
    max-width: 54ch;
    margin: 0;
}

.home-hero__art {
    display: none;
}

@media (min-width: 900px) {
    body.theme-2026 .home-hero .n2n-band__inner {
        flex-direction: row;
        align-items: center;
        gap: clamp(32px, 5vw, 60px);
    }

    body.theme-2026 .home-hero .dashboard-hero-copy {
        flex: 1 1 auto;
        min-width: 0;
    }

    body.theme-2026 .home-hero__art {
        display: block;
        flex: 0 0 clamp(320px, 34vw, 440px);
        width: clamp(320px, 34vw, 440px);
        transform: rotate(-1.6deg);
        filter: drop-shadow(0 14px 30px rgba(0, 0, 0, 0.42));
    }

    body.theme-2026 .home-hero__art img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: 3px;
    }
}

/* ---------- The form card
 *
 * Scoped to `.home-form-band .email-container-wrapper`, NOT to `.home-card`.
 * The reply from canvasser.resend_assignment_email is a fragment carrying only
 * `email-container-wrapper` - it does not know about `.home-card` - so styling
 * that class alone left the "Thanks!" state as bare text on the band. */
body.theme-2026 .home-form-band .email-container-wrapper {
    width: auto;
    max-width: 640px;
    margin: 0 auto;
    padding: clamp(26px, 3.6vw, 40px) clamp(22px, 3.4vw, 40px) clamp(28px, 3.8vw, 38px);
    background-color: var(--n2n-card);
    background-image: none;
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 10px 28px rgba(0, 33, 62, 0.18);
    color: var(--n2n-navy);
}

/* style.css sets `display: flex; align-items: center` here, which put the
 * kicker and the heading side by side on one line. */
body.theme-2026 .home-form-band .email-container-header {
    display: block;
    margin-bottom: 4px;
}

/* The houses closing band is the last one, so it absorbs any leftover viewport
 * height rather than leaving a strip above the footer. */
body.theme-2026 .home-closing-band {
    flex-grow: 1;
}

/* Also set by the swapped-in reply as `<h3 class="email-title pl-0">Thanks!</h3>`,
 * so both states have to look the same. */
/* style.css sets `display: inline; padding-left: 8px` on `.email-title`, which
 * indented the heading relative to its kicker. */
body.theme-2026 .home-form-band .email-title {
    display: block;
    padding-left: 0;
    font-family: var(--n2n-font-heading);
    font-weight: 700;
    font-size: clamp(24px, 2.6vw, 32px);
    line-height: 1.05;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .home-form-band .email-title::before {
    display: none;
}

body.theme-2026 .home-card__lede,
body.theme-2026 .home-form-band .email-container-content p {
    font-family: var(--n2n-font-body);
    font-size: 16px;
    line-height: 1.55;
    color: var(--n2n-navy);
}

body.theme-2026 .home-card__lede {
    margin: 0 0 18px;
    max-width: 54ch;
}

.home-form__label {
    display: block;
    margin: 0 0 6px;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
}

.home-form__row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

body.theme-2026 .home-form__input {
    flex: 1 1 240px;
    min-width: 0;
    font-size: 17px;
}

@media (max-width: 560px) {
    /* `flex: 1 1 240px` sizes the MAIN axis, so once this row turns vertical the
     * basis would become a 240px-tall input. */
    body.theme-2026 .home-form__input {
        flex: 0 0 auto;
        width: 100%;
    }

    .home-form__submit {
        width: 100%;
        justify-content: center;
    }
}

/* ---------- Closing band
 *
 * The dashboard's navy paper band and street, reused.
 *
 * min-height is required: the street is an absolutely-positioned layer in a
 * band with `overflow: hidden`, and this band is usually empty (the
 * return-assignments panel only renders in two states). Without it the band
 * collapses below the artwork height and crops the rooflines flat. */
.neighbors-closing-band {
    min-height: clamp(190px, 25vw, 380px);
    /* `.n2n-bands > .n2n-band:last-child` doesn't reach this band - the partial
     * ends with the map scripts and the achievements data div, so this is not
     * the wrapper's last child. */
    flex-grow: 1;
}

/* Same measure as the two bands above it, so the sheet starts on the page's one
 * left edge. At the narrower 786px default the band's content began ~175px
 * inboard of everything else on the page. */
.neighbors-closing-band .n2n-band__inner {
    max-width: 1100px;
}

.neighbors-closing-band .dashboard-paper {
    max-width: 640px;
}

/* Returning your list is a way out, not the thing the page wants you to do, so
 * it takes the same quiet navy the dashboard's secondary buttons take rather
 * than the primary red. */
body.theme-2026 .neighbors-return-button {
    background-color: var(--n2n-navy);
    color: var(--n2n-cream);
    margin-top: 6px;
}

body.theme-2026 .neighbors-return-button:hover {
    background-color: var(--n2n-navy-mid);
    color: var(--n2n-cream);
}

/* Links inside a paper sheet get their ink flipped to navy by the slate-band
 * rules above, which also costs them the only other thing marking them as
 * links. */
body.theme-2026 .neighbors-return-paper a {
    text-decoration: underline;
    font-weight: 600;
}

/* ---------- Simple page head
 *
 * Script, Printouts, Contact, Achievements. Same navy masthead as the
 * dashboard and neighbors heroes, minus the art and the wide measure - these
 * are reading pages, so the head sits on the same 786px column as the text
 * below it. The yellow rule is repeated from `.n2n-band--hero` rather than
 * factored out. */
.n2n-band--pagehead {
    border-bottom: 4px solid var(--n2n-yellow);
    padding-top: clamp(24px, 3vw, 40px);
    padding-bottom: clamp(26px, 3.2vw, 42px);
}

/* Must out-specify `body.theme-2026 .n2n-band--navy p` (0,2,2), which would
 * otherwise paint the kicker cream along with the rest of the band. */
body.theme-2026 p.n2n-pagehead__kicker {
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

body.theme-2026 h1.n2n-pagehead__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(32px, 4vw, 48px);
    font-weight: 700;
    line-height: 1.0;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 14px;
}

body.theme-2026 p.n2n-pagehead__sub {
    color: rgba(255, 251, 239, 0.86);
    font-size: 17px;
    line-height: 1.55;
    max-width: 58ch;
    margin: 0;
}

/* ---------- Simple page body band */

/* `.page` is `justify-content: space-between` with a fixed height, so leftover
 * viewport height is split above and below a middle child that doesn't grow.
 * These pages are short, so the body band absorbs it. */
.n2n-page-band {
    flex-grow: 1;
    padding-bottom: clamp(36px, 4.5vw, 64px);
}

/* One measure for the whole page, head included. */
.n2n-page-band .n2n-band__inner {
    max-width: 786px;
}

.n2n-page-cta {
    margin-top: clamp(22px, 2.6vw, 34px);
}

/* Secondary here: on the printouts page the printout itself is the errand, so
 * the way onward shouldn't compete with it in red. */
body.theme-2026 .n2n-page-cta--quiet {
    background-color: var(--n2n-navy);
    color: var(--n2n-cream);
}

body.theme-2026 .n2n-page-cta--quiet:hover {
    background-color: var(--n2n-navy-mid);
    color: var(--n2n-cream);
}

/* ---------- Script sheet */

body.theme-2026 .n2n-script-text {
    /* The script is stored with real line breaks between its branches; without
     * pre-wrap they collapse into one paragraph. The neighbor detail page has
     * always set this. */
    white-space: pre-wrap;
    font-family: var(--n2n-font-body);
    /* Larger than body copy: read off a phone at arm's length, mid-conversation. */
    font-size: 18px;
    line-height: 1.65;
    color: var(--n2n-navy);
    margin: 0;
}

/* Sheet sized to the measure rather than insetting the text - capping the text
 * alone left ~150px of bare paper down the right side. 680px minus padding
 * lands lines at ~62 characters. */
.n2n-script-paper {
    max-width: 680px;
}

/* Required: nothing else in the theme sets a link colour on a light band, so
 * the "no script was found" fallback rendered its mailto in browser-default
 * blue. */
body.theme-2026 .n2n-script-text a {
    color: var(--n2n-navy-mid);
    text-decoration: underline;
    font-weight: 600;
}

/* ---------- Printout card
 * Wide, with the icon beside the text rather than stacked above it - there is
 * only ever one of these, so it is not a grid card. */
.n2n-printout-card {
    display: flex;
    align-items: flex-start;
    /* Not the full measure: stretched to 786px the card put ~380px of empty
     * cream to the right of its own button. */
    max-width: 560px;
    gap: clamp(18px, 2.4vw, 28px);
    width: 100%;
    padding: clamp(22px, 3vw, 32px) clamp(22px, 3vw, 34px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    /* Same accent foot the dashboard's resource cards carry, in the red that
     * marks the primary action on the page. */
    border-bottom: 6px solid var(--n2n-red);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.18);
}

.n2n-printout-card__icon {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    max-width: 64px;
}

.n2n-printout-card__body {
    min-width: 0;
}

body.theme-2026 .n2n-printout-card__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(22px, 2.2vw, 28px);
    line-height: 1.08;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .n2n-printout-card__title::before {
    display: none;
}

body.theme-2026 .n2n-printout-card__meta {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 7px 0 0;
}

.n2n-printout-card__button {
    margin-top: 18px;
}

@media (max-width: 560px) {
    /* The icon beside the text leaves too little room for the button label at
       phone widths, so it moves above. */
    .n2n-printout-card {
        flex-direction: column;
        gap: 16px;
    }
}

/* Second paragraph in the page head, set apart from the first. */
body.theme-2026 p.n2n-pagehead__note {
    margin-top: 12px;
    padding-left: 14px;
    border-left: 3px solid var(--n2n-cyan);
    font-size: 16px;
}

/* An interface label quoted inside a sentence. Set in the button face so it
 * reads as the thing on the screen rather than as emphasis - the button it
 * points at is the same family. */
.n2n-ui-label {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    letter-spacing: 0.04em;
    color: var(--n2n-yellow);
    white-space: nowrap;
}

/* ---------- Teal neighbourhood band
 *
 * The deck's third line-art paper, after the yellow and the white. Used only on
 * Canvassing Tips, which is read once before a shift and can carry a ground
 * colour of its own.
 *
 * Mean measures #15c8d4. background-color first, so a 404 leaves the right
 * colour. */
.n2n-band--teal {
    background-color: #1ad0da;
    background-image: url("assets/textures/band-teal-neighborhood.jpg");
    background-size: cover;
    background-position: center;
    color: var(--n2n-navy);
}

/* The one page head that is not navy, so it needs the yellow rule to separate
 * two light fields. */
.n2n-tips-head {
    border-bottom: 4px solid var(--n2n-yellow);
    padding-top: clamp(26px, 3.2vw, 44px);
    padding-bottom: clamp(28px, 3.4vw, 46px);
}

/* Cream highlights behind the kicker and heading, as on the yellow band - the
 * line-art is busy and navy type on it loses its edges. */
.n2n-band--teal .dashboard-headline {
    position: relative;
    display: inline-block;
    padding: 0;
    margin-bottom: 14px;
}

.n2n-band--teal .dashboard-kicker,
.n2n-band--teal .dashboard-section-title {
    width: fit-content;
    background: var(--n2n-cream);
    border-radius: 2px;
}

.n2n-band--teal .dashboard-kicker {
    line-height: 1.02;
    padding: 2px 8px;
    margin: 0 0 9px;
}

.n2n-band--teal .dashboard-section-title {
    line-height: 0.98;
    padding: 2px 8px;
    margin: 0;
}

body.theme-2026 .n2n-band--teal .dashboard-kicker,
body.theme-2026 .n2n-band--teal .dashboard-section-title {
    color: var(--n2n-navy);
    opacity: 1;
}

/* `.n2n-band__inner > * { width: 100% }` would stretch the highlight block to
 * the full measure, and a cream bar spanning the band is not a highlight. Same
 * exception the dashboard's headline needs. */
.n2n-band__inner > .n2n-tips-headline {
    width: auto;
    max-width: 100%;
    align-self: flex-start;
}

/* This page's title is the page's h1, so it runs at hero scale rather than the
 * section scale `.dashboard-section-title` normally carries. */
body.theme-2026 h1.n2n-tips-title {
    font-size: clamp(30px, 3.6vw, 44px);
}

/* Same measure as the cards below, so the heading, the intro and the tips all
 * start on one left edge - at the default 786px the head sat ~57px inboard of
 * the cards and the two bands looked misregistered. */
.n2n-tips-head .n2n-band__inner {
    max-width: 900px;
}

body.theme-2026 .n2n-tips-intro {
    color: var(--n2n-navy);
    font-size: 17px;
    line-height: 1.55;
    max-width: 62ch;
    margin: 0;
}

/* ---------- Tip groups
 * Wide stacked cards, not the dashboard's four-up grid - each group holds three
 * full sentences.
 */
.n2n-tips-band .n2n-band__inner {
    max-width: 900px;
    gap: clamp(18px, 2.2vw, 26px);
}

.n2n-tip-group {
    width: 100%;
    padding: clamp(20px, 2.6vw, 30px) clamp(20px, 2.8vw, 34px) clamp(18px, 2.4vw, 26px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.16);
}

/* One brand colour per group, as the dashboard does across its resource cards -
 * the accent is what tells you at a glance that you have moved from one group
 * to the next while scrolling past a wall of body text. */
.n2n-tip-group:nth-of-type(1) { border-bottom: 6px solid var(--n2n-accent-cyan); }
.n2n-tip-group:nth-of-type(2) { border-bottom: 6px solid var(--n2n-yellow); }
.n2n-tip-group:nth-of-type(3) { border-bottom: 6px solid var(--n2n-red); }

.n2n-tip-group__head {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 12px;
}

.n2n-tip-group__icon {
    flex: 0 0 auto;
    width: 52px;
    height: 52px;
    max-width: 52px;
}

body.theme-2026 .n2n-tip-group__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(21px, 2.1vw, 26px);
    line-height: 1.05;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .n2n-tip-group__title::before {
    display: none;
}

.n2n-tip-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.n2n-tip-list li {
    position: relative;
    padding: 0 0 0 26px;
    margin: 0;
    font-family: var(--n2n-font-body);
    font-size: 16px;
    line-height: 1.6;
    color: var(--n2n-navy);
}

.n2n-tip-list li + li {
    margin-top: 12px;
    padding-top: 12px;
    /* A hairline between tips rather than more whitespace: three long sentences
     * with only a gap between them read as one paragraph that lost its way. */
    border-top: 1px solid rgba(0, 33, 62, 0.14);
}

/* The reference site marks its criteria lists with an arrow rather than a disc,
 * which is the right shape here too - each of these is an instruction. */
.n2n-tip-list li::before {
    content: "\2192";
    position: absolute;
    left: 0;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    color: var(--n2n-red);
}

.n2n-tip-list li + li::before {
    top: 12px;
}

@media (max-width: 560px) {
    .n2n-tip-group__icon {
        width: 44px;
        height: 44px;
        max-width: 44px;
    }
}

/* ---------- Contact card
 * Same shape as the printout card. The address was previously a link inside a
 * sentence. */
.n2n-contact-card {
    display: flex;
    align-items: flex-start;
    gap: clamp(18px, 2.4vw, 28px);
    width: 100%;
    max-width: 560px;
    padding: clamp(22px, 3vw, 32px) clamp(22px, 3vw, 34px);
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.18);
}

.n2n-contact-card__icon {
    flex: 0 0 auto;
    width: 60px;
    height: 60px;
    max-width: 60px;
}

.n2n-contact-card__body {
    min-width: 0;
}

body.theme-2026 .n2n-contact-card__label {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 0 0 4px;
}

/* The address itself is the content, so it is set at heading scale - but in the
 * body face, because an email address in condensed uppercase is harder to read
 * back to someone than it is to look at. */
body.theme-2026 .n2n-contact-card__address {
    display: inline-block;
    font-family: var(--n2n-font-body);
    font-weight: 700;
    font-size: clamp(17px, 1.8vw, 21px);
    line-height: 1.25;
    color: var(--n2n-navy);
    text-decoration: underline;
    /* Long support addresses must break rather than push the card wide. */
    overflow-wrap: anywhere;
}

body.theme-2026 .n2n-contact-card__meta {
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
    margin: 8px 0 0;
}

.n2n-contact-card__button {
    margin-top: 18px;
}

@media (max-width: 560px) {
    .n2n-contact-card {
        flex-direction: column;
        gap: 16px;
    }
}

/* ---------- Achievements
 * Twelve tiles in one column ran to ~3000px. The count leads in the head, the
 * campaign goal gets its own band, and the tiles are a grid.
 */

.n2n-achievements-score .dashboard-stat__num {
    /* No second stat to sit beside, so it can run larger than the paired stats
     * on the dashboard and neighbors heroes. */
    font-size: clamp(46px, 5vw, 64px);
}

.n2n-score__of {
    font-size: 0.5em;
    color: rgba(255, 251, 239, 0.65);
    letter-spacing: 0.01em;
}

body.theme-2026 .n2n-achievements-head .n2n-pagehead__sub {
    margin-top: 4px;
}

/* Campaign goal band. The navy paper stock from the dashboard's closing band,
 * but with the street suppressed - a ground line belongs at the foot of a page,
 * and this one sits in the middle of it. */
.n2n-goal-band {
    padding-bottom: clamp(26px, 3.2vw, 44px);
}

/* The campaign-goal band sits mid-page, so it takes the navy field without the
 * houses - a row of rooflines belongs at the foot of a page, not between two
 * sections. (This used to suppress the separate street layer; the houses are
 * part of the band background now, so it suppresses the image instead.) */
.n2n-goal-band {
    background-image: none;
}

.n2n-goal {
    width: 100%;
}

.n2n-goal__stats {
    margin-bottom: 14px;
}

.n2n-goal__bar {
    max-width: 520px;
    margin-bottom: 10px;
}

body.theme-2026 .n2n-goal__caption {
    color: rgba(255, 251, 239, 0.85);
    font-size: 15px;
    margin: 0;
}

/* ---------- Badge grid */

.n2n-achievements-band .n2n-band__inner {
    /* Three tiles at ~270px plus gaps. */
    max-width: 900px;
}

.n2n-achievements {
    /* style.css caps `.achievements-container` at 786px and centres it, which
     * would re-narrow the grid inside the wider band. */
    width: 100%;
    max-width: none;
    margin: 0;
    padding: 0;
    gap: clamp(28px, 3.4vw, 44px);
}

.n2n-badge-group {
    width: 100%;
}

body.theme-2026 .n2n-badge-group__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(20px, 2vw, 25px);
    line-height: 1.1;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0 0 4px;
    padding-bottom: 8px;
    border-bottom: 2px solid var(--n2n-navy);
}

.n2n-badge-grid {
    display: grid;
    /* Explicit column counts, not auto-fill: at this measure auto-fill resolved to
     * four columns, leaving every three-badge row with a gap. `auto-fit` would
     * stretch the lone Champion badge across the full measure. */
    grid-template-columns: 1fr;
    gap: clamp(14px, 1.6vw, 20px);
    margin-top: 16px;
}

/* Centred so the artwork leads. The only centred layout in the app - every
 * other page is a task list. */
.n2n-badge {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 22px 18px 16px;
    background-color: var(--n2n-card);
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid rgba(0, 33, 62, 0.18);
    box-shadow: 0 6px 18px rgba(0, 33, 62, 0.14);
}

.n2n-badge--earned {
    border-bottom-color: #0f7a4a;
}

.n2n-badge--progress {
    border-bottom-color: var(--n2n-yellow);
}

/* Not started reads as unearned rather than as broken: same card, quieter. */
.n2n-badge--locked {
    background-color: rgba(252, 248, 238, 0.72);
    box-shadow: 0 3px 10px rgba(0, 33, 62, 0.08);
}

body.theme-2026 .n2n-badge__icon {
    width: 88px;
    height: 88px;
    max-width: 88px;
    /* style.css gives it a 16px right margin, written for the old horizontal
     * tile - in a centred one it shifts the artwork 8px off axis. */
    margin: 0 0 10px;
}

/* The unearned artwork is already drawn pale; this stops it competing with the
 * earned badges around it without washing it out completely. */
body.theme-2026 .n2n-badge--locked .n2n-badge__icon {
    opacity: 0.55;
}

.n2n-badge__body {
    flex: 1 1 auto;
    width: 100%;
}

body.theme-2026 .n2n-badge__title {
    font-family: var(--n2n-font-heading);
    font-size: 19px;
    line-height: 1.1;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0 0 5px;
}

body.theme-2026 .n2n-badge__desc {
    font-family: var(--n2n-font-body);
    font-size: 14px;
    line-height: 1.45;
    color: var(--n2n-navy-mid);
    margin: 0;
}

body.theme-2026 .n2n-badge__rewards {
    font-size: 13px;
    color: var(--n2n-navy-mid);
    margin-top: 8px;
}

/* `position: static` is required: style.css absolutely positions all three mark
 * classes at `top: 12px; right: 12px`, which in a centred tile puts the chip on
 * top of the artwork. */
body.theme-2026 .n2n-badge__status {
    position: static;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin: 14px 0 0;
    padding: 5px 11px 4px;
    border-radius: 999px;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 11px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    line-height: 1;
}

body.theme-2026 .n2n-badge--earned .n2n-badge__status {
    background: #e2f3ea;
    color: #0f6b41;
}

body.theme-2026 .n2n-badge--progress .n2n-badge__status {
    background: #fff1ce;
    color: #7a5200;
}

body.theme-2026 .n2n-badge--locked .n2n-badge__status {
    background: rgba(0, 33, 62, 0.07);
    color: var(--n2n-navy-mid);
}

.n2n-badge__status .completed-icon {
    width: 12px;
    height: 12px;
}

.n2n-badge-group__action {
    margin-top: 18px;
}

/* ---------- Referral block, inside the recruiting group */

.n2n-referral {
    margin-top: 20px;
    padding: 20px 22px 22px;
    background-color: var(--n2n-card);
    border-radius: 3px;
    border-left: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 4px 14px rgba(0, 33, 62, 0.12);
}

body.theme-2026 .n2n-referral__text {
    font-size: 15px;
    line-height: 1.5;
    color: var(--n2n-navy);
    margin: 0 0 6px;
}

body.theme-2026 .n2n-referral__link {
    display: inline-block;
    font-family: var(--n2n-font-body);
    font-weight: 600;
    font-size: 15px;
    color: var(--n2n-navy-mid);
    text-decoration: underline;
    overflow-wrap: anywhere;
}

.n2n-referral .n2n-badge-group__action {
    margin-top: 14px;
}


@media (min-width: 560px) {
    .n2n-badge-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 900px) {
    .n2n-badge-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

/* ---------- Home page (/)
 *
 * The front door. Its job is the "email me my dashboard link" form, but it also
 * has to explain the program to anyone arriving cold, so it takes the same band
 * structure as the canvasser pages: navy hero, the form on paper, three steps,
 * houses closing into the footer.
 */

body.theme-2026.home-body .page {
    height: auto;
    min-height: 100%;
}

.home-hero .n2n-band__inner {
    max-width: 1100px;
}

body.theme-2026 p.home-hero__kicker {
    color: var(--n2n-yellow);
    margin: 0 0 2px;
}

body.theme-2026 h1.home-hero__title {
    font-family: var(--n2n-font-heading);
    font-size: clamp(34px, 4.4vw, 56px);
    font-weight: 700;
    line-height: 1.0;
    letter-spacing: -0.005em;
    text-transform: uppercase;
    color: var(--n2n-cream);
    margin: 0 0 16px;
}

body.theme-2026 p.home-hero__lede {
    color: rgba(255, 251, 239, 0.86);
    font-size: 17px;
    line-height: 1.55;
    max-width: 54ch;
    margin: 0;
}

.home-hero__art {
    display: none;
}

@media (min-width: 900px) {
    body.theme-2026 .home-hero .n2n-band__inner {
        flex-direction: row;
        align-items: center;
        gap: clamp(32px, 5vw, 60px);
    }

    body.theme-2026 .home-hero .dashboard-hero-copy {
        flex: 1 1 auto;
        min-width: 0;
    }

    body.theme-2026 .home-hero__art {
        display: block;
        flex: 0 0 clamp(320px, 34vw, 440px);
        width: clamp(320px, 34vw, 440px);
        transform: rotate(-1.6deg);
        filter: drop-shadow(0 14px 30px rgba(0, 0, 0, 0.42));
    }

    body.theme-2026 .home-hero__art img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: 3px;
    }
}

/* ---------- The form card
 *
 * Scoped to `.home-form-band .email-container-wrapper`, NOT to `.home-card`.
 * The reply from canvasser.resend_assignment_email is a fragment carrying only
 * `email-container-wrapper` - it does not know about `.home-card` - so styling
 * that class alone left the "Thanks!" state as bare text on the band. */
body.theme-2026 .home-form-band .email-container-wrapper {
    width: auto;
    max-width: 640px;
    margin: 0 auto;
    padding: clamp(26px, 3.6vw, 40px) clamp(22px, 3.4vw, 40px) clamp(28px, 3.8vw, 38px);
    background-color: var(--n2n-card);
    background-image: none;
    border: 0;
    border-radius: 3px;
    border-bottom: 6px solid var(--n2n-accent-cyan);
    box-shadow: 0 10px 28px rgba(0, 33, 62, 0.18);
    color: var(--n2n-navy);
}

/* style.css sets `display: flex; align-items: center` here, which put the
 * kicker and the heading side by side on one line. */
body.theme-2026 .home-form-band .email-container-header {
    display: block;
    margin-bottom: 4px;
}

/* The houses closing band is the last one, so it absorbs any leftover viewport
 * height rather than leaving a strip above the footer. */
body.theme-2026 .home-closing-band {
    flex-grow: 1;
}

/* Also set by the swapped-in reply as `<h3 class="email-title pl-0">Thanks!</h3>`,
 * so both states have to look the same. */
/* style.css sets `display: inline; padding-left: 8px` on `.email-title`, which
 * indented the heading relative to its kicker. */
body.theme-2026 .home-form-band .email-title {
    display: block;
    padding-left: 0;
    font-family: var(--n2n-font-heading);
    font-weight: 700;
    font-size: clamp(24px, 2.6vw, 32px);
    line-height: 1.05;
    text-transform: uppercase;
    color: var(--n2n-navy);
    margin: 0;
}

body.theme-2026 .home-form-band .email-title::before {
    display: none;
}

body.theme-2026 .home-card__lede,
body.theme-2026 .home-form-band .email-container-content p {
    font-family: var(--n2n-font-body);
    font-size: 16px;
    line-height: 1.55;
    color: var(--n2n-navy);
}

body.theme-2026 .home-card__lede {
    margin: 0 0 18px;
    max-width: 54ch;
}

.home-form__label {
    display: block;
    margin: 0 0 6px;
    font-family: var(--n2n-font-button);
    font-weight: 600;
    font-size: 12px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--n2n-navy-mid);
}

.home-form__row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

body.theme-2026 .home-form__input {
    flex: 1 1 240px;
    min-width: 0;
    font-size: 17px;
}

@media (max-width: 560px) {
    /* `flex: 1 1 240px` sizes the MAIN axis, so once this row turns vertical the
     * basis would become a 240px-tall input. */
    body.theme-2026 .home-form__input {
        flex: 0 0 auto;
        width: 100%;
    }

    .home-form__submit {
        width: 100%;
        justify-content: center;
    }
}

/* Support line, under the card rather than stranded in the artwork below. */
body.theme-2026 .home-support {
    width: 100%;
    max-width: 640px;
    margin: 18px auto 0;
    font-size: 15px;
    color: var(--n2n-navy-mid);
}

body.theme-2026 .home-support a {
    color: var(--n2n-navy-mid);
    text-decoration: underline;
    font-weight: 600;
}

/* ---------- Closing band
 * Artwork only, so it needs a height of its own: the houses are a background on
 * a band with no content, and would otherwise collapse to nothing. */
.home-closing-band {
    min-height: clamp(190px, 26vw, 400px);
    padding: 0;
}

/* ---------- Script branch headings
 * The copy is 18px but `h2` keeps style.css's 12px, and theme-2026.css swaps
 * the 2px letter-spacing for 0.005em - so the heading read weaker than the
 * "- If yes:" labels under it. Size and spacing restored, brand face kept. */
body.theme-2026 .n2n-script-text h2 {
    font-size: 15px;
    letter-spacing: 0.1em;
    margin: 28px 0 10px;
}

/* ---------- Script spacing
 * Scripts are stored with newlines between blocks - PA-007 has two blank lines
 * at ten of them - and `pre-wrap` renders those on top of the margins. Collapse
 * on the container, then put `pre-wrap` back on the blocks so a break inside a
 * paragraph still works; four scripts rely on that. */
body.theme-2026 .n2n-script-text:has(p, h2, ul, ol) {
    white-space: normal;
}

/* `:has()` never matches the five scripts stored as plain text, so those keep
 * `pre-wrap`. Without `:has()` support the rule drops and nothing changes. */
body.theme-2026 .n2n-script-text p,
body.theme-2026 .n2n-script-text h2,
body.theme-2026 .n2n-script-text li {
    white-space: pre-wrap;
}

/* The stored newlines no longer render, so the rhythm comes from the margin. */
body.theme-2026 .n2n-script-text p {
    margin: 0 0 14px;
}
