/* ==========================================================================
   Home-page background designs — the "panes" family.

   Every design here is the SAME idea: a field of tiled panes separated by
   gutters, lit from two corners. They differ only in pane size, gutter weight
   and edge treatment. Earlier revisions carried unrelated designs (mesh, aurora,
   grid, dots, sunburst, topographic, duotone, spotlight, and four louder bento
   spin-offs); they were removed on purpose — panes won.

   The page paints its atmosphere on three layers:
     body            — the base wash
     body::before    — the lighting (fixed, z-index 0), shared by every variant
     body::after     — the pane structure, painted ON TOP of the lighting
   Everything else sits at z-index >= 1, so all three stay decorative and never
   take pointer events.

   A design is selected by `document.documentElement.dataset.design` (see
   commons/home-designs.js). Every rule is scoped `html[data-design="…"]`, which
   out-specifies the page's own `body` / `body::before` rules regardless of
   stylesheet order — that's why this file can be included anywhere in <head>.

   If this stylesheet or its script fails to load, no `data-design` attribute is
   set and the page falls back to its own inline mesh background. That fallback
   is the only reason the inline `body::before` in index.html still exists.

   WHY no filter:blur anywhere: a blurred fixed layer re-rasterizes on every
   viewport change, and on mobile the address bar resizes the viewport
   constantly — that caused visible blinking. Softness comes from gradient
   falloff, never from a blur filter.

   ADDING A VARIANT: write it as a single `body::after` rule below using the
   shared colour vars, then add it to DESIGNS in the .js and give it a `.hb-sw`
   swatch. Nothing else should need touching.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Shared by every variant.
   -------------------------------------------------------------------------- */

/* The page's own ::before bleeds 8% past the top/bottom and drifts; a tiled
   pattern needs it pinned to the viewport instead (a drifting grid smears). */
html[data-design] body::before {
    top: 0;
    bottom: 0;
    animation: none;
}

html[data-design] body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

html[data-design] body {
    background: var(--page);

    /* Gutter colours, flipped per theme so each variant is written once.
         --hb-gut   the normal gutter fill (reads as the page showing between panes)
         --hb-seam  a thin high-contrast seam, for the hairline variant
         --hb-lift  the bright top edge that makes a pane look raised */
    --hb-gut: rgba(255, 255, 255, 0.72);
    --hb-seam: rgba(74, 69, 102, 0.14);
    --hb-lift: rgba(255, 255, 255, 0.95);

    /* Crisper chrome. The single biggest "why does this look blurry" contributor
       was the heavy backdrop-filter on the glass panels — at .65 alpha + 14px
       blur the background smeared through every surface. Denser glass makes them
       read as material sitting ON the background instead of dissolved into it. */
    --glass: rgba(255, 255, 255, 0.84);
    --border: rgba(74, 69, 102, 0.12);
}

html[data-design] body.dark {
    --hb-gut: rgba(10, 8, 16, 0.5);
    --hb-seam: rgba(255, 255, 255, 0.07);
    --hb-lift: rgba(255, 255, 255, 0.14);
    --glass: rgba(26, 23, 38, 0.82);
    --border: rgba(255, 255, 255, 0.1);
}

/* The lighting layer — identical for every variant, which is what keeps them
   recognisably one family however the tiling changes. */
html[data-design] body::before {
    background:
        radial-gradient(50% 44% at 12% 6%, rgba(139, 92, 246, 0.3), transparent 68%),
        radial-gradient(54% 48% at 92% 92%, rgba(14, 165, 233, 0.24), transparent 68%),
        radial-gradient(40% 36% at 78% 12%, rgba(236, 72, 153, 0.18), transparent 68%);
}

html[data-design] body.dark::before {
    background:
        radial-gradient(50% 44% at 12% 6%, rgba(139, 92, 246, 0.28), transparent 68%),
        radial-gradient(54% 48% at 92% 92%, rgba(14, 165, 233, 0.22), transparent 68%),
        radial-gradient(40% 36% at 78% 12%, rgba(236, 72, 153, 0.16), transparent 68%);
}

/* ==========================================================================
   PANES — the original. 150px panes, 12px gutters.
   ========================================================================== */
html[data-design='panes'] body::after {
    background-image:
        repeating-linear-gradient(0deg, transparent 0 138px, var(--hb-gut) 138px 150px),
        repeating-linear-gradient(90deg, transparent 0 138px, var(--hb-gut) 138px 150px);
}

/* ==========================================================================
   PANES · WIDE — 210px panes, 18px gutters. The same recipe at a larger scale,
   so fewer panes cross the hero and the field reads calmer.
   ========================================================================== */
html[data-design='panes-wide'] body::after {
    background-image:
        repeating-linear-gradient(0deg, transparent 0 192px, var(--hb-gut) 192px 210px),
        repeating-linear-gradient(90deg, transparent 0 192px, var(--hb-gut) 192px 210px);
}

/* ==========================================================================
   PANES · FINE — 108px panes, 8px gutters. The other direction: a denser weave
   that reads as texture more than as layout.
   ========================================================================== */
html[data-design='panes-fine'] body::after {
    background-image:
        repeating-linear-gradient(0deg, transparent 0 100px, var(--hb-gut) 100px 108px),
        repeating-linear-gradient(90deg, transparent 0 100px, var(--hb-gut) 100px 108px);
}

/* ==========================================================================
   PANES · SOFT — 150px panes with ROUNDED corners.
   A gradient can't round a rectangle, but a hard-edged disc parked on each grid
   intersection eats the four corners around it, and its arc becomes their
   radius. The disc layer must be offset so the intersection lands at the CENTRE
   of its own tile (144 - 75 = 69px); at any other offset the disc is clipped by
   the tile edge and you get quarter-circles instead of one round blob.
   ========================================================================== */
/* Opaque gutters, unlike every other variant. The disc overlaps the two gutter
   bands at each crossing, and translucent layers COMPOUND where they overlap —
   with the usual .72 white that shows up as a bright dot on every intersection
   instead of a rounded corner. An opaque fill paints the same colour however
   many layers stack. `--page` already flips per theme, so one line covers both. */
html[data-design='panes-soft'] body {
    --hb-gut: var(--page);
}

html[data-design='panes-soft'] body::after {
    background-image:
        radial-gradient(circle at 50% 50%, var(--hb-gut) 0 14px, transparent 14.5px),
        repeating-linear-gradient(0deg, transparent 0 138px, var(--hb-gut) 138px 150px),
        repeating-linear-gradient(90deg, transparent 0 138px, var(--hb-gut) 138px 150px);
    background-size:
        150px 150px,
        auto,
        auto;
    background-position:
        69px 69px,
        0 0,
        0 0;
}

/* ==========================================================================
   PANES · SEAM — panes nearly touching, split by a 2px high-contrast line
   instead of a wide gutter. Closest to a real bento grid's card borders.
   ========================================================================== */
html[data-design='panes-seam'] body::after {
    background-image:
        repeating-linear-gradient(0deg, transparent 0 148px, var(--hb-seam) 148px 150px),
        repeating-linear-gradient(90deg, transparent 0 148px, var(--hb-seam) 148px 150px);
}

/* ==========================================================================
   PANES · LIFT — the standard grid plus a 2px bright line along each pane's top
   edge, so the panes read as slightly raised. The gutter leads the period and
   the highlight follows it, which puts the line exactly at the pane's top.
   ========================================================================== */
html[data-design='panes-lift'] body::after {
    background-image:
        repeating-linear-gradient(
            180deg,
            var(--hb-gut) 0 12px,
            var(--hb-lift) 12px 14px,
            transparent 14px 150px
        ),
        repeating-linear-gradient(90deg, var(--hb-gut) 0 12px, transparent 12px 150px);
}

/* ==========================================================================
   THE PICKER
   A floating control, bottom-left, that switches the variant live. Sits under
   the modals (z-index 70) on purpose so it can never cover a dialog.
   ========================================================================== */
.hb-picker {
    position: fixed;
    left: 14px;
    bottom: 14px;
    z-index: 64;
    font-family: 'Nunito', system-ui, sans-serif;
}

.hb-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 38px;
    padding: 0 14px 0 11px;
    font-family: inherit;
    font-weight: 800;
    font-size: 0.82rem;
    color: var(--ink-soft);
    background: var(--glass);
    backdrop-filter: blur(10px);
    border: 1.5px solid var(--border);
    border-radius: 999px;
    box-shadow: var(--shadow-sm);
    cursor: pointer;
    transition:
        color 0.15s,
        border-color 0.15s,
        transform 0.2s var(--spring);
}

.hb-btn:hover {
    color: var(--ink);
    border-color: var(--lav);
    transform: translateY(-1px);
}

.hb-btn:active {
    transform: scale(0.96);
}

.hb-btn svg {
    width: 17px;
    height: 17px;
    flex: none;
}

.hb-panel {
    position: absolute;
    left: 0;
    bottom: 46px;
    width: 268px;
    max-height: min(78vh, 600px);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--surface);
    border: 1.5px solid var(--border);
    border-radius: 16px;
    padding: 7px;
    box-shadow: 0 24px 60px -18px rgba(74, 69, 102, 0.45);
    animation: hbPop 0.16s ease both;
}

.hb-panel[hidden] {
    display: none;
}

@keyframes hbPop {
    from {
        opacity: 0;
        transform: translateY(6px) scale(0.98);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

.hb-head {
    font-size: 0.66rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-faint);
    padding: 7px 10px 6px;
}

.hb-opt {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    text-align: left;
    border: none;
    background: none;
    cursor: pointer;
    padding: 6px 8px;
    border-radius: 11px;
    font-family: inherit;
    transition: background 0.15s;
}

.hb-opt:hover {
    background: var(--surface-3);
}

.hb-opt .hb-nm {
    font-weight: 700;
    font-size: 0.86rem;
    color: var(--ink);
    line-height: 1.2;
}

.hb-opt .hb-dsc {
    display: block;
    font-weight: 600;
    font-size: 0.72rem;
    color: var(--ink-faint);
    margin-top: 2px;
    /* One line per row — a wrapping description makes the rows uneven. */
    white-space: nowrap;
}

.hb-opt .hb-ck {
    margin-left: auto;
    width: 16px;
    height: 16px;
    flex: none;
    color: var(--accent-ink2);
    opacity: 0;
}

.hb-opt[aria-checked='true'] .hb-ck {
    opacity: 1;
}

.hb-opt[aria-checked='true'] {
    background: var(--surface-3);
}

/* Swatches — miniature versions of each recipe, scaled to read at 42x30. They
   carry each variant's structure, not its exact pixel geometry. Each one only
   sets --hb-sw-panes; the shared rule composes it over the corner glow, and the
   gutter colour flips with the theme like the designs' own. */
.hb-sw {
    width: 42px;
    height: 30px;
    flex: none;
    border-radius: 8px;
    border: 1.5px solid var(--border-2);
    background-color: var(--page);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.4);
    background-image: var(--hb-sw-panes), var(--hb-sw-glow);
    --hb-sw-gut: rgba(255, 255, 255, 0.92);
    --hb-sw-seam: rgba(74, 69, 102, 0.3);
    --hb-sw-glow: radial-gradient(70% 70% at 8% 4%, rgba(139, 92, 246, 0.55), transparent 72%),
        radial-gradient(70% 70% at 96% 96%, rgba(14, 165, 233, 0.45), transparent 72%);
}

body.dark .hb-sw {
    --hb-sw-gut: rgba(10, 8, 16, 0.72);
    --hb-sw-seam: rgba(255, 255, 255, 0.22);
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.06);
}

.hb-sw[data-sw='panes'] {
    --hb-sw-panes: repeating-linear-gradient(0deg, transparent 0 11px, var(--hb-sw-gut) 11px 13px),
        repeating-linear-gradient(90deg, transparent 0 11px, var(--hb-sw-gut) 11px 13px);
}

.hb-sw[data-sw='panes-wide'] {
    --hb-sw-panes: repeating-linear-gradient(0deg, transparent 0 16px, var(--hb-sw-gut) 16px 19px),
        repeating-linear-gradient(90deg, transparent 0 16px, var(--hb-sw-gut) 16px 19px);
}

.hb-sw[data-sw='panes-fine'] {
    --hb-sw-panes: repeating-linear-gradient(0deg, transparent 0 7px, var(--hb-sw-gut) 7px 8px),
        repeating-linear-gradient(90deg, transparent 0 7px, var(--hb-sw-gut) 7px 8px);
}

/* Same disc trick as the design, at swatch scale: 13px tiles, disc centred on
   the intersection (12 - 6.5 = 5.5px offset). */
.hb-sw[data-sw='panes-soft'] {
    --hb-sw-panes: radial-gradient(circle at 50% 50%, var(--hb-sw-gut) 0 3px, transparent 3.5px),
        repeating-linear-gradient(0deg, transparent 0 11px, var(--hb-sw-gut) 11px 13px),
        repeating-linear-gradient(90deg, transparent 0 11px, var(--hb-sw-gut) 11px 13px);
    background-size:
        13px 13px,
        auto,
        auto,
        auto,
        auto;
    background-position:
        5.5px 5.5px,
        0 0,
        0 0,
        0 0,
        0 0;
}

.hb-sw[data-sw='panes-seam'] {
    --hb-sw-panes: repeating-linear-gradient(0deg, transparent 0 12px, var(--hb-sw-seam) 12px 13px),
        repeating-linear-gradient(90deg, transparent 0 12px, var(--hb-sw-seam) 12px 13px);
}

.hb-sw[data-sw='panes-lift'] {
    --hb-sw-panes: repeating-linear-gradient(
            180deg,
            var(--hb-sw-gut) 0 2px,
            rgba(255, 255, 255, 0.95) 2px 3px,
            transparent 3px 13px
        ),
        repeating-linear-gradient(90deg, var(--hb-sw-gut) 0 2px, transparent 2px 13px);
}

/* Phones: the button would sit on top of the composer, so shrink it to an icon
   and let the panel use the full width. */
@media (max-width: 560px) {
    .hb-picker {
        left: 10px;
        bottom: 10px;
    }

    .hb-btn {
        height: 34px;
        padding: 0 10px;
    }

    .hb-btn .hb-label {
        display: none;
    }

    .hb-panel {
        width: min(84vw, 268px);
    }
}
