/* The Door - intranet theme.
   The house's stone: DanceMore Manor's labradorite, read dark green, raked by a diagonal
   cleft of moonlight; elven-silver inscription with light held from within the moss in
   the carved groove, not chrome glow on metal. Schiller flashes blue in the stone where the
   light meets a crystal (schiller.js); gold only behind the door. Cold stone throughout;
   no warmth anywhere in this file except the sanctioned danger/alarm and ember exceptions.
   The rave cave (indra-theme) is the interior of the mountain; this is the threshold.
   See intent/vision/the-door-theme.md.

   Janus rule of text: inscriptions are art (moss-glow, slow reveal); body and data are
   steel (high contrast, zero shadow, instantly legible). */

:root {
    --basalt:         #0e1611;   /* the stone's deep green-black ground (labradorite, read dark green) */
    --basalt-slab:    #1a2221;   /* the slab face: the manor's cabinet slate-sage, a hair blue of the stone */
    --basalt-lit:     #222c2a;   /* dusk light on the top plane */
    --moss-deep:      #1f3729;
    --moss:           #30523b;
    --moss-live:      #70ac71;   /* living moss in the lit recesses; candidate hex, tunable */
    --lichen:         #a3aeac;   /* dry crustose sage-grey */
    --fog:            #c5cbc3;   /* body text: fog-lit, steel-legible */
    --fog-dim:        #909990;   /* recessed chrome only */
    --cedar:          #b07a50;   /* danger/alarm only: destructive affordances, never decoration */
    --cedar-deep:     #6e4626;   /* danger/alarm only, see --cedar */
    --ember:          #e3c677;   /* the one warm glow permitted behind the door; line color. Candle
                                     Glow, the stone's gold flash. See the-door-theme.md, Second exception. */
    --ember-fill:     rgba(227, 198, 119, .13);
    --ember-ink:      #f5e8cc;
    --ember-halo:     rgba(227, 198, 119, .48);
    --silver:         #cdd7d2;   /* elven silver, damp */
    --silver-lit:     #e4ece8;   /* moonlight core */
    --glow:           #4bbadb;   /* schiller cyan, the stone's blue flash; matte and wet */
    --serif: 'Cormorant Garamond', 'EB Garamond', 'Iowan Old Style', Georgia, serif;
    --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    --mono: ui-monospace, 'SFMono-Regular', Menlo, Consolas, monospace;

    /* Diagonal Cleft surface textures (shared by every page, door and interior alike). */
    --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 .5 0 0 0 0 .53 0 0 0 0 .5 0 0 0 .5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
    --mottle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 500 900'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.02 0.008' numOctaves='4' seed='3'/%3E%3CfeColorMatrix values='0 0 0 0 .05 0 0 0 0 .07 0 0 0 0 .06 0 0 0 .95 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23m)'/%3E%3C/svg%3E");

    /* Chiseled basalt geometry: asymmetric cooling-joint bevels, not a rectangle. */
    --cleft: polygon(0 0, calc(100% - 26px) 0, 100% 22px,
                     100% 100%, 26px 100%, 0 calc(100% - 22px));

    /* Dark-adaptation floor/ceiling contract. 0 = floor (AA-legible resting state,
       --fog against --basalt-slab), 1 = ceiling (today's resolved ithildin/h1 hover
       appearance, frozen). Default is 1 so anything without JS renders at ceiling. */
    --presence: 1;

    color-scheme: dark;
}

@media (prefers-reduced-motion: reduce) {
    :root { --presence: 1 !important; }
}
@media (hover: none), (pointer: coarse) {
    :root { --presence: 1 !important; }
}

/* Screen-reader-only text: visually hidden, still in the accessibility
   tree. bootstrap.min.css defines the same recipe but is not loaded on
   this layout (base.css is the theme's own global stylesheet); several
   views already reference .sr-only, so it belongs here, not per-feature. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

@font-face {
    font-family: 'RedactedScript-Bold';
    src: url('/indra-theme/fonts/RedactedScript-Bold.woff2') format('woff2');
    font-weight: bold;
    font-style: normal;
}
.redacted-font { font-family: 'RedactedScript-Bold', sans-serif; }

* { margin: 0; padding: 0; box-sizing: border-box; }

/* Ground: the Diagonal Cleft. A dark green stone face raked by a diagonal rift of
   moonlight, moss seeping along the lower cleft. One surface for the whole intranet, door
   and interior alike. The mineral layers ride body::after. */
body {
    font-family: var(--sans);
    color: var(--fog);
    background-color: var(--basalt);
    background-image:
        linear-gradient(108deg,transparent 36%,rgba(140,172,150,0.025) 45%,rgba(140,172,150,0.038) 50%,rgba(140,172,150,0.025) 55%,transparent 64%),
        radial-gradient(58% 52% at 30% 17%,rgba(140,172,150,0.035),transparent 67%),
        linear-gradient(108deg,transparent 58%,rgba(110,164,112,0.022) 66%,transparent 74%),
        radial-gradient(60% 24% at 50% 104%,rgba(31,58,42,.33),transparent 72%),
        radial-gradient(135% 100% at 30% 30%,transparent 32%,rgba(4,7,5,.9) 100%),
        linear-gradient(160deg,#14201a 0%,#0d1510 48%,#070c09 100%);
    background-attachment: fixed;
    min-height: 100vh;
    overflow-x: hidden;
    line-height: 1.7;
    display: flex;
    flex-direction: column;
}

/* Mottled wet-stone tooth + fine grain over the whole face. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    opacity: 0.3;
    mix-blend-mode: overlay;
    background: var(--mottle), var(--grain);
    background-size: 800px 1200px, 180px 180px;
    background-attachment: fixed;
}

/* The stone: labradorite's mineral layers over the ground (hornblende, chlorite,
   serpentine, feldspar, the grey-blue labradorite body, a trace of iron), soft contour
   ripples of light under polish, faint fractures, moss in the joints. Painted normally so
   they add hue, not white. Every filter renders in sRGB: the SVG default (linearRGB)
   lifts these colours toward a grey haze. Recipe L, intent/concepts/labradorite-lab/. */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image:
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'turbulence'%20baseFrequency%3D'0.003%200.008'%20numOctaves%3D'3'%20seed%3D'17'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.43137254901960786%200%200%200%200%200.6431372549019608%200%200%200%200%200.4392156862745098%20-12%200%200%200%201'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.052000000000000005'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'turbulence'%20baseFrequency%3D'0.003%200.008'%20numOctaves%3D'3'%20seed%3D'17'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.011764705882352941%200%200%200%200%200.03137254901960784%200%200%200%200%200.0196078431372549%20-20%200%200%200%201'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.0675'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'turbulence'%20baseFrequency%3D'0.0022%200.0055'%20numOctaves%3D'3'%20seed%3D'3'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.22745098039215686%200%200%200%200%200.27450980392156865%200%200%200%200%200.23529411764705882%20-13%200%200%200%201'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.09'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.004%200.012'%20numOctaves%3D'5'%20seed%3D'3'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.24705882352941178%200%200%200%200%200.3686274509803922%200%200%200%200%200.2901960784313726%201%200%200%200%200'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'table'%20tableValues%3D'0%200%200%200%200%200%200.42%200.147%200%200%200%200'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.007%200.02'%20numOctaves%3D'4'%20seed%3D'17'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.00784313725490196%200%200%200%200%200.023529411764705882%200%200%200%200%200.01568627450980392%201%200%200%200%200'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'table'%20tableValues%3D'0%200%200%200%200%200%200.5%200.175%200%200%200%200'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0035'%20numOctaves%3D'3'%20seed%3D'31'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.058823529411764705%200%200%200%200%200.10196078431372549%200%200%200%200%200.0784313725490196%205%200%200%200%20-2.3000000000000003'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.5599999999999999'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0022'%20numOctaves%3D'3'%20seed%3D'38'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.16470588235294117%200%200%200%200%200.2823529411764706%200%200%200%200%200.2196078431372549%205%200%200%200%20-2.6500000000000004'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.48'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0040'%20numOctaves%3D'3'%20seed%3D'45'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.23529411764705882%200%200%200%200%200.33725490196078434%200%200%200%200%200.20784313725490197%205%200%200%200%20-2.9'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.30400000000000005'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0030'%20numOctaves%3D'3'%20seed%3D'52'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.2901960784313726%200%200%200%200%200.37254901960784315%200%200%200%200%200.3333333333333333%205%200%200%200%20-3'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.36000000000000004'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0045'%20numOctaves%3D'3'%20seed%3D'59'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.19215686274509805%200%200%200%200%200.27058823529411763%200%200%200%200%200.2980392156862745%205%200%200%200%20-2.8000000000000003'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.36000000000000004'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E"),
        url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%201000%201000'%3E%3Cfilter%20id%3D'f'%20x%3D'0'%20y%3D'0'%20width%3D'100%25'%20height%3D'100%25'%20color-interpolation-filters%3D'sRGB'%3E%3CfeTurbulence%20type%3D'fractalNoise'%20baseFrequency%3D'0.0060'%20numOctaves%3D'3'%20seed%3D'66'%20stitchTiles%3D'stitch'%2F%3E%3CfeColorMatrix%20values%3D'0%200%200%200%200.23137254901960785%200%200%200%200%200.17254901960784313%200%200%200%200%200.12549019607843137%205%200%200%200%20-3.4000000000000004'%2F%3E%3CfeComponentTransfer%3E%3CfeFuncA%20type%3D'linear'%20slope%3D'0.17600000000000002'%2F%3E%3C%2FfeComponentTransfer%3E%3C%2Ffilter%3E%3Crect%20width%3D'100%25'%20height%3D'100%25'%20filter%3D'url(%23f)'%2F%3E%3C%2Fsvg%3E");
    background-size: 700px 700px, 700px 700px, 1000px 1000px, 1000px 1000px, 700px 700px, 1000px 1000px, 1137px 1137px, 1274px 1274px, 1411px 1411px, 1548px 1548px, 1685px 1685px;
}

/* Schiller (schiller_controller.js): soft crystals in the stone that flash when the light,
   the pointer, meets them at their angle. Opacity is the only thing that moves. */
.ds-schiller {
    position: fixed;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}
.ds-shard {
    position: absolute;
    opacity: 0;
    mix-blend-mode: screen;
}
.ds-shard-bloom {
    position: absolute;
    inset: -35%;
    background: radial-gradient(closest-side, var(--c1), transparent);
    opacity: .22;
    filter: blur(14px);
}
.ds-shard-facet {
    position: absolute;
    inset: 0;
    clip-path: var(--poly);
    background:
        repeating-linear-gradient(0deg, rgba(0,0,0,.16) 0 1px, transparent 1px 4px),
        radial-gradient(70% 90% at 38% 45%, rgba(255,255,255,.2), transparent 70%),
        linear-gradient(var(--grad), transparent 0%, var(--c1) 22%, var(--c2) 52%, var(--c1) 80%, transparent 100%);
    filter: blur(1.6px);
}
.content-wrapper {
    position: relative;
    z-index: 2;
    flex: 1 0 auto;
    width: 100%;
    max-width: 800px;
    margin: 0 auto;
    padding: 6rem 2rem 5rem 2rem;
}

/* The slab: a carved panel of the house's joinery. A raised-panel groove runs 14px inside
   the edge (light catching its upper-left lip, shadow its lower-right), drawn as background
   layers because ::before is the facet and ::after is spent on some pages. The inset band
   along the foot is the countertop's thickness. No border, no radius. */
.crystal-panel {
    position: relative;
    z-index: 1;
    padding: 2rem 2.25rem;
    margin: 1.75rem 0;
    background-color: var(--basalt-slab);
    background-image:
        linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)),
        linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)),
        linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)),
        linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)),
        linear-gradient(rgba(205,215,210,.07), rgba(205,215,210,.07)),
        linear-gradient(rgba(205,215,210,.07), rgba(205,215,210,.07)),
        linear-gradient(rgba(0,0,0,.38), rgba(0,0,0,.38)),
        linear-gradient(rgba(0,0,0,.38), rgba(0,0,0,.38)),
        linear-gradient(174deg, rgba(75, 186, 219, 0.03) 0%, transparent 34%),
        linear-gradient(178deg, var(--basalt-lit) 0%, var(--basalt-slab) 82%),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.02 0.03' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.60 0 0 0 0 0.50 0 0 0 0.08 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
    background-position:
        left 14px top 14px, left 14px bottom 21px, left 14px top 14px, right 14px top 14px,
        left 15px top 15px, left 15px top 15px, left 15px bottom 22px, right 15px top 15px,
        0 0, 0 0, 0 0;
    background-size:
        calc(100% - 28px) 1px, calc(100% - 28px) 1px, 1px calc(100% - 35px), 1px calc(100% - 35px),
        calc(100% - 30px) 2px, 2px calc(100% - 37px), calc(100% - 30px) 2px, 2px calc(100% - 37px),
        auto, auto, 190px 190px;
    background-repeat: no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat, repeat;
    clip-path: var(--cleft);
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.5), inset 0 -7px 0 rgba(0, 0, 0, 0.34), inset 0 -8px 0 rgba(205, 215, 210, 0.07);
}

/* Chiseled fracture facet: light catches only the top-left cleavage planes. */
.crystal-panel::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    clip-path: var(--cleft);
    background: linear-gradient(135deg,
        rgba(170, 190, 186, 0.2) 0%,
        rgba(48, 82, 59, 0.12) 28%,
        transparent 58%);
    background: linear-gradient(135deg,
        rgba(170, 190, 186, 0.2) 0%,
        color-mix(in oklab, rgba(48, 82, 59, 0.12) calc((1 - var(--presence)) * 100%), rgba(112, 172, 113, 0.12) calc(var(--presence) * 100%)) 28%,
        transparent 58%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
            mask-composite: exclude;
    padding: 1.5px;
}

.crystal-panel img { max-width: 100%; height: auto; }

/* Inscription: carved silver, faint at rest, moss lit from within on presence. */
h1, h2, h3 {
    font-family: var(--serif);
    font-weight: 600;
    color: var(--silver);
}

h1 {
    font-size: 2.7rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    text-align: center;
    margin-bottom: 1.1rem;
    will-change: color, text-shadow;
}

/* Moss drying under a warm hand: the groove phosphoresces from within. */
.crystal-panel:hover h1,
.crystal-panel:focus-within h1 {
    color: var(--silver-lit);
    text-shadow:
        0 0 1px rgba(228, 236, 232, 0.9),
        0 0 6px rgba(75, 186, 219, 0.6),
        0 0 15px rgba(44, 74, 70, 0.8),
        0 2px 22px rgba(14, 22, 17, 0.95);
    transition: color 3.2s cubic-bezier(0.16, 1, 0.3, 1),
                text-shadow 3.8s cubic-bezier(0.16, 1, 0.3, 1);
}

h2 { font-size: 1.7rem; letter-spacing: 0.04em; margin-bottom: 1rem; }
h3 { font-size: 1.35rem; margin-bottom: 0.7rem; color: var(--lichen); }

/* Body and data: steel. Legible, matte, no mystery. */
p { color: var(--fog); margin-bottom: 1rem; }
.subtitle { font-size: 1.15rem; color: var(--lichen); margin-bottom: 1.4rem; }
ul, ol { margin: 1rem 0; padding-left: 1.4rem; color: var(--fog); }
li { margin-bottom: 0.5rem; }

a {
    color: var(--glow);
    text-decoration: none;
    border-bottom: 1px solid rgba(75, 186, 219, 0.28);
    transition: color 0.4s ease, border-color 0.4s ease, text-shadow 0.4s ease;
}
a:hover {
    color: var(--silver-lit);
    border-bottom-color: rgba(228, 236, 232, 0.5);
    text-shadow: 0 0 8px rgba(75, 186, 219, 0.4);
}

/* The ithildin contract: an ambient floor->ceiling climb (driven by --presence, the
   page-wide presence clock, never below AA at 0) composed with a local sustained-linger
   resolve (held hover/focus-within) that carries the element to ceiling faster, on the
   same curve. .ithildin is kept as an alias so existing uses keep working. */
.ds-ithildin, .ithildin, h1 {
    color: var(--fog); /* fallback for browsers without color-mix() */
    color: color-mix(in oklab, var(--fog) calc((1 - var(--presence)) * 100%), var(--silver-lit) calc(var(--presence) * 100%));
    text-shadow: 0 0 6px rgba(75,186,219, calc(var(--presence) * 0.6)),
                 0 0 15px rgba(48,82,59, calc(var(--presence) * 0.8));
}
.ds-ithildin:hover, .ds-ithildin:focus-within, :hover > .ds-ithildin,
.ithildin:hover, .ithildin:focus-within, :hover > .ithildin {
    color: var(--silver-lit);
    text-shadow: 0 0 6px rgba(75,186,219,0.6), 0 0 15px rgba(48,82,59,0.8);
    transition: color 3.2s cubic-bezier(0.16,1,0.3,1), text-shadow 3.8s cubic-bezier(0.16,1,0.3,1);
}

code {
    background: rgba(48, 82, 59, 0.32);
    color: var(--glow);
    padding: 0.2em 0.4em;
    font-family: 'SF Mono', Consolas, monospace;
    font-size: 0.9em;
}
pre {
    background: rgba(0, 0, 0, 0.4);
    padding: 1rem;
    overflow-x: auto;
    margin: 1rem 0;
    clip-path: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%);
}
pre code { background: none; padding: 0; color: var(--fog); }

/* A fault line: a cold silvered groove, replaces every generic accent line. */
.ds-lintel, hr {
    height: 4px;
    border: none;
    margin: 1.5rem 0;
    background:
        linear-gradient(90deg, transparent 0%, rgba(205,215,210,0.4) 15%,
            rgba(48,82,59,0.9) 50%, rgba(205,215,210,0.4) 85%, transparent 100%);
    box-shadow: 0 1px 3px rgba(0,0,0,0.8);
}

/* Navigation: a low basalt lintel over the door. */
.site-nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 100;
    height: 60px;
    background: linear-gradient(180deg, rgba(22,32,26,0.96), rgba(14,22,17,0.96));
    box-shadow: 0 2px 12px rgba(0,0,0,0.6), inset 0 -1px 0 rgba(48,82,59,0.35);
    display: flex;
    justify-content: center;
}
.site-nav-inner {
    display: flex; align-items: center; gap: 1rem;
    width: 100%; max-width: 800px; padding: 0 2rem;
}
.site-nav a {
    display: inline-block;
    padding: 18px 0;
    margin-right: 1em;
    font-weight: 600;
    color: var(--lichen);
    border-bottom: none;
    transition: color 0.4s ease, text-shadow 0.4s ease;
}
.site-nav a:hover {
    border-bottom: none;
    color: var(--silver-lit);
    text-shadow: 0 0 8px rgba(75,186,219,0.4);
}
.site-nav a.active {
    color: var(--glow);
    text-shadow: 0 0 6px rgba(75,186,219,0.6), 0 0 15px rgba(48,82,59,0.8);
}

.site-nav-links {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 1rem;
}

/* Logged-out actions (just Login): never collapsed behind the hamburger. */
.site-nav-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 1rem;
}

/* Sign-in pill: quiet ghost affordance, not a browser-default box. */
.ghost-login {
    background: none;
    border: none;
    border-bottom: 1px solid transparent;
    font-family: inherit;
    font-size: 0.7rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--fog-dim);
    padding: 0.4rem 0.2rem;
    cursor: pointer;
    transition: color 0.4s ease, border-color 0.4s ease;
}
.ghost-login:hover,
.ghost-login:focus {
    color: var(--glow);
    border-bottom-color: rgba(75,186,219,0.28);
    outline: none;
}

/* Hamburger: hidden above the collapse breakpoint, a seam-cut glyph below it. */
.nav-toggle {
    display: none;
    margin-left: auto;
    width: 44px;
    height: 44px;
    padding: 0;
    border: none;
    background: none;
    cursor: pointer;
}
.nav-toggle-glyph,
.nav-toggle-glyph::before,
.nav-toggle-glyph::after {
    display: block;
    width: 22px;
    height: 2px;
    background: var(--lichen);
    box-shadow: 0 0 4px rgba(75,186,219,0.25);
    transition: background 0.3s ease, box-shadow 0.3s ease;
}
.nav-toggle-glyph {
    position: relative;
    margin: 0 auto;
}
.nav-toggle-glyph::before,
.nav-toggle-glyph::after {
    content: "";
    position: absolute;
    left: 0;
}
.nav-toggle-glyph::before { top: -7px; }
.nav-toggle-glyph::after { top: 7px; }
.nav-toggle:hover .nav-toggle-glyph,
.nav-toggle:hover .nav-toggle-glyph::before,
.nav-toggle:hover .nav-toggle-glyph::after,
.nav-toggle:focus-visible .nav-toggle-glyph,
.nav-toggle:focus-visible .nav-toggle-glyph::before,
.nav-toggle:focus-visible .nav-toggle-glyph::after {
    background: var(--glow);
    box-shadow: 0 0 6px rgba(75,186,219,0.5);
}
.nav-toggle:focus-visible {
    outline: 1px solid var(--glow);
    outline-offset: 3px;
}

@media (max-width: 640px) {
    .nav-toggle { display: block; }
    .site-nav-links {
        display: none;
        position: absolute;
        top: 60px; left: 0; right: 0;
        flex-direction: column;
        align-items: stretch;
        gap: 0;
        background: linear-gradient(180deg, rgba(22,32,26,0.98), rgba(14,22,17,0.98));
        box-shadow: 0 4px 12px rgba(0,0,0,0.6), inset 0 -1px 0 rgba(48,82,59,0.35);
        padding: 0.5rem 1.5rem 1rem;
    }
    .site-nav-links.site-nav-links--open {
        display: flex;
    }
    .site-nav-links a,
    .site-nav-links form {
        margin-right: 0;
        width: 100%;
    }
    .site-nav-links .btn {
        width: 100%;
        text-align: center;
        margin-top: 0.5rem;
    }
}

/* Footer */
.site-footer {
    flex-shrink: 0;
    width: 100%;
    display: flex; justify-content: center;
    height: 40px;
    background: rgba(14,22,17,0.96);
    box-shadow: 0 -2px 12px rgba(0,0,0,0.6), inset 0 1px 0 rgba(48,82,59,0.25);
    z-index: 1;
}
.site-footer span {
    display: flex; align-items: center;
    max-width: 800px; width: 100%; padding: 0 2rem;
    color: var(--fog-dim); font-size: 0.85rem;
}
.site-footer a.pi-login { color: var(--lichen); border-bottom: none; font-size: 1.2rem; }
.site-footer a.pi-login:hover { color: var(--glow); }

/* Ambient data bar: steel data, foxfire glyphs, no rainbow. */
.ambient-bar {
    position: fixed;
    top: 60px; left: 0; right: 0;
    z-index: 99;
    height: 28px;
    background: rgba(14,22,17,0.92);
    overflow: hidden;
    display: flex; align-items: center; justify-content: flex-start;
    padding: 0 clamp(1.2rem, 4vw, 3rem);
    box-shadow: inset 0 1px 0 rgba(48,82,59,0.4);
}
/* A single static line: fade its trailing edge instead of letting content hard-cut
   against the viewport edge. */
.ambient-bar {
    mask-image: linear-gradient(to right, black 85%, transparent 100%);
    -webkit-mask-image: linear-gradient(to right, black 85%, transparent 100%);
}
.ticker-track {
    display: inline-flex; align-items: center; height: 100%;
    white-space: nowrap;
    font-family: var(--mono); letter-spacing: 0.1em;
}
.ticker-item { font-size: 0.78rem; color: var(--fog-dim); }
.ticker-item .mdi { color: var(--glow); }
.ticker-sep { margin: 0 1.2em; color: var(--moss); font-size: 0.78rem; }

/* Buttons: small chiseled stones. Enter is foxfire; destructive is cedar. */
.btn {
    display: inline-block;
    padding: 0.6rem 1.3rem;
    font-size: 0.95rem;
    cursor: pointer;
    border: none;
    background: var(--basalt-lit);
    color: var(--lichen);
    clip-path: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%);
    box-shadow: inset 0 1px 0 rgba(163,172,163,0.12), 0 3px 8px rgba(0,0,0,0.5);
    transition: color 0.3s ease, box-shadow 0.4s ease, background 0.3s ease;
}
.btn-success, .btn-primary, .btn-info { color: var(--glow); }
.btn-success:hover, .btn-primary:hover, .btn-info:hover {
    color: var(--silver-lit);
    background: #1b2118;
    box-shadow: inset 0 1px 0 rgba(75,186,219,0.25), 0 0 14px rgba(75,186,219,0.22), 0 3px 8px rgba(0,0,0,0.5);
}
.btn-warning { color: var(--fog); }
.btn-warning:hover { color: var(--silver); background: #222c2a; }
.btn-danger { color: var(--cedar); }
.btn-danger:hover { color: #d09a72; background: #1c1610; box-shadow: inset 0 1px 0 rgba(176,122,80,0.3), 0 3px 8px rgba(0,0,0,0.5); }
.btn-secondary { color: var(--fog); }
.btn-secondary:hover { color: var(--silver); background: #222c2a; }

/* Forms: a cut trough in the stone. Also carries every native text-like
   control app-wide, so a bare input/select/textarea without the class still
   reads as the-door rather than default browser chrome. */
.form-control,
input[type="text"], input[type="email"], input[type="number"], input[type="password"],
input[type="search"], input[type="tel"], input[type="url"],
input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"],
textarea, select {
    font-family: inherit;
    width: 100%;
    padding: 0.75rem 1rem;
    background: rgba(0,0,0,0.4);
    border: none;
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), inset 0 0 0 1px var(--moss);
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), inset 0 0 0 1px
        color-mix(in oklab, var(--moss) calc((1 - var(--presence)) * 100%), var(--moss-live) calc(var(--presence) * 100%));
    color: var(--fog);
    font-size: 1rem;
    clip-path: polygon(0 5px, 5px 0, 100% 0, 100% calc(100% - 5px), calc(100% - 5px) 100%, 0 100%);
}
input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"], input[type="week"] {
    padding: 0.75rem 0.5rem;
}
.form-control:focus,
input[type="text"]:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus,
input[type="search"]:focus, input[type="tel"]:focus, input[type="url"]:focus,
input[type="date"]:focus, input[type="time"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="week"]:focus,
textarea:focus, select:focus {
    outline: none;
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), inset 0 0 0 1px var(--glow), 0 0 10px rgba(75,186,219,0.15);
}
.form-control::placeholder, input::placeholder, textarea::placeholder { color: var(--fog-dim); }
select { cursor: pointer; }
textarea { resize: vertical; }

input[type="file"] { color: var(--fog); font-size: 0.95rem; }
input[type="file"]::file-selector-button {
    padding: 0.5rem 1rem;
    margin-right: 0.75rem;
    border: none;
    border-radius: 0;
    background: rgba(0,0,0,0.4);
    box-shadow: inset 0 0 0 1px var(--moss);
    color: var(--fog);
    cursor: pointer;
}
input[type="file"]::file-selector-button:hover { color: var(--silver); box-shadow: inset 0 0 0 1px var(--lichen); }

input[type="checkbox"], input[type="radio"] {
    accent-color: var(--glow);
    width: auto;
    box-shadow: none;
}

/* A field Rails wraps for a failed validation: keep the wrapper out of layout,
   tint the control itself in the sanctioned danger register. */
.field_with_errors { display: contents; }
.field_with_errors .form-control,
.field_with_errors input,
.field_with_errors select,
.field_with_errors textarea {
    box-shadow: inset 0 2px 5px rgba(0,0,0,0.6), inset 0 0 0 1px rgba(200,107,90,0.55);
}
.field_with_errors label { color: #d68575; }

/* The seam slot: a deep, nearly-invisible trough in wet basalt with the foxfire seep
   on focus. Any input that should read as this instance of the one signature gesture
   takes this class; an ID stays available on the element only as a JS hook. */
.ds-seam-field {
    box-shadow:
        inset 0 2px 5px rgba(0,0,0,0.7),
        inset 0 0 0 1px var(--moss),
        inset 0 -1px 8px rgba(75,186,219,0.1);
    box-shadow:
        inset 0 2px 5px rgba(0,0,0,0.7),
        inset 0 0 0 1px color-mix(in oklab, var(--moss) calc((1 - var(--presence)) * 100%), var(--moss-live) calc(var(--presence) * 100%)),
        inset 0 -1px 8px rgba(75,186,219,0.1);
}
.ds-seam-field:focus {
    box-shadow:
        inset 0 2px 5px rgba(0,0,0,0.7),
        inset 0 0 0 1px var(--glow),
        inset 0 -1px 14px rgba(75,186,219,0.22),
        0 0 16px rgba(75,186,219,0.14);
}

/* Alerts */
.alert { padding: 1rem 1.2rem; margin-bottom: 1rem;
    clip-path: polygon(0 6px, 6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%); }
.alert-success { background: rgba(48,82,59,0.42); box-shadow: inset 0 0 0 1px rgba(75,186,219,0.3); color: var(--glow); }
.alert-danger { background: rgba(200,107,90,0.15); box-shadow: inset 0 0 0 1px rgba(200,107,90,0.32); color: #d68575; }

/* Hot rejection: the door turns on you. Ember/scorched-basalt register, the one place
   cedar/amber/red is sanctioned (the-door DNA reserves warm tones for danger/alarm).
   The error copy sits directly on the heated panel: no box-in-a-box. */
.rejection-notice {
    margin-bottom: 1rem;
    color: #e8a878;
}
.rejection-notice .form-help { color: #c07a52; }

/* A single body-level toggle (door-angry) drives the whole surface: both crystal-panels,
   the ambient scene. .crystal-panel.is-rejected is the same heated look scoped to one
   panel, for the (non-terminal) step-2 field-validation case.

   The COLOR changeover is a HARD SNAP, deliberately: no transition, no filter, anywhere
   in this block. The door slams; it does not fade. This is also a correctness
   constraint, not just a style choice: contrast()/saturate()/brightness() filters push
   light pixels (the h1, panel highlights, the noise-texture grain) toward white for the
   duration of the punch, and a CSS transition on background-color necessarily crossfades
   through intermediate colors on its way to ember, both of which read as an unwanted
   white flash. Nothing below can produce a frame lighter than the calm baseline: no
   filter, no transition on any property, no lightening mix-blend-mode.

   The one exception is `door-strike`, below, on .door-page: a TRANSFORM-ONLY shake
   (translateX + a small rotate wobble, decaying). transform cannot alter a pixel's
   luminance, so it carries the "flinch" back in without touching the no-flash
   guarantee above. */
@keyframes door-strike {
    0%   { transform: translateX(0) rotate(0); }
    10%  { transform: translateX(-9px) rotate(-0.5deg); }
    22%  { transform: translateX(8px) rotate(0.4deg); }
    34%  { transform: translateX(-6px) rotate(-0.3deg); }
    46%  { transform: translateX(4px) rotate(0.2deg); }
    60%  { transform: translateX(-2px) rotate(-0.1deg); }
    75%  { transform: translateX(1px) rotate(0); }
    100% { transform: translateX(0) rotate(0); }
}
body.door-angry .door-page {
    animation: door-strike 0.42s cubic-bezier(0.36, 0.07, 0.19, 0.97) 1;
    transform-origin: 50% 50%;
}
@media (prefers-reduced-motion: reduce) {
    body.door-angry .door-page { animation: none; }
}
body.door-angry {
    background-color: #170c07;
    background-image:
        linear-gradient(108deg, transparent 36%, rgba(210,110,55,.13) 45%, rgba(230,135,70,.17) 50%, rgba(210,110,55,.13) 55%, transparent 64%),
        radial-gradient(52% 58% at 30% 16%, rgba(220,120,60,.15), transparent 64%),
        linear-gradient(108deg, transparent 58%, rgba(190,70,30,.15) 66%, transparent 74%),
        radial-gradient(60% 24% at 50% 104%, rgba(94,20,8,.48), transparent 72%),
        repeating-linear-gradient(108deg,
            rgba(0,0,0,.34) 0 2px, rgba(0,0,0,0) 2px 60px,
            rgba(255,180,120,.03) 60px 61px, rgba(0,0,0,0) 61px 120px),
        radial-gradient(135% 100% at 30% 30%, transparent 32%, rgba(10,5,4,.92) 100%),
        linear-gradient(160deg, #241208 0%, #170c07 48%, #0d0503 100%);
}
/* The calm body::after is the green stone and .ds-schiller is screen-blended light (a
   lightening blend by definition). Drop both outright while angry rather than retint
   them: content: none removes the generated box, so nothing green or screen-blended is
   left to interact with the ember changeover. */
body.door-angry::after {
    content: none;
}
body.door-angry .ds-schiller { display: none; }

body.door-angry .crystal-panel,
.crystal-panel.is-rejected {
    background-color: #1c0e06;
    background-image:
        linear-gradient(174deg, rgba(255,130,60,0.08) 0%, transparent 40%),
        linear-gradient(178deg, #33190a 0%, #1c0e06 82%),
        url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.04 0.18' numOctaves='3'/%3E%3CfeColorMatrix values='0 0 0 0 0.75 0 0 0 0 0.38 0 0 0 0 0.18 0 0 0 0.12 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23b)'/%3E%3C/svg%3E");
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.6), inset 0 0 46px rgba(255,70,20,0.22);
}
body.door-angry .crystal-panel::before,
.crystal-panel.is-rejected::before {
    background: linear-gradient(135deg,
        rgba(255,150,70,0.30) 0%,
        rgba(120,30,10,0.20) 28%,
        transparent 58%);
}
/* The moss seep at the base of every panel flares ember instead of foxfire green. */
body.door-angry .door-page .crystal-panel::after {
    background: linear-gradient(90deg, #ff7a3a, transparent);
    opacity: 0.7;
}

/* Total anger sweep: everywhere else on the page that still reads foxfire teal
   (var(--glow)), moss/lichen green (var(--moss), var(--lichen)), or a teal/green
   accent line while the door is angry, retinted to the same ember register. Every
   override here is a static color/box-shadow snap, same as the rest of this block:
   no transition, no filter, so it cannot reintroduce the flash. */
body.door-angry .ticker-item .mdi { color: #ff8a4a; }
body.door-angry .ticker-sep { color: #c07a52; }
body.door-angry .ambient-bar { box-shadow: inset 0 1px 0 rgba(120,30,10,0.4); }
body.door-angry .subtitle { color: #e8a878; }
/* h1's always-on ithildin glow (a foxfire text-shadow, independent of hover) and its
   stronger hover/focus-within flare inside a panel both retint; the base --silver text
   color itself is left alone (it's a neutral damp-silver, not green/teal). */
body.door-angry h1,
body.door-angry .ds-ithildin,
body.door-angry .ithildin {
    text-shadow: 0 0 6px rgba(255,110,50,0.55), 0 0 15px rgba(120,30,10,0.6);
}
body.door-angry .crystal-panel:hover h1,
body.door-angry .crystal-panel:focus-within h1 {
    text-shadow:
        0 0 1px rgba(255,225,200,0.9),
        0 0 6px rgba(255,120,50,0.6),
        0 0 15px rgba(120,30,10,0.8),
        0 2px 22px rgba(14,22,17,0.95);
}
/* The generic link style (foxfire color + teal underline) covers the door-sitemark
   logo link's underline and any other anchor on the page. */
body.door-angry a {
    color: #ff8a4a;
    border-bottom-color: rgba(255,110,50,0.28);
}
body.door-angry a:hover {
    color: #ffcfa8;
    border-bottom-color: rgba(255,180,120,0.5);
    text-shadow: 0 0 8px rgba(255,110,50,0.4);
}
body.door-angry .ghost-login:hover,
body.door-angry .ghost-login:focus {
    color: #ff8a4a;
    border-bottom-color: rgba(255,110,50,0.28);
}

/* The welcome MELTS: the door withdraws its greeting from someone who does not belong,
   past readable, into an illegible dripping smear. Only the welcome panel's TEXT (h1 +
   the two subtitle lines), not the panel material and not the error panel. Replaces an
   earlier "hold the eroded text readable, then blur/recede it" sequencing the operator
   tried and rejected in favor of this: no hold, the melt starts immediately and simply
   takes time to complete, which is what makes it visible as motion rather than a static
   blur.

   The liquify itself is `filter: url(#door-melt)` (defined inline in
   registrations/new.html.erb): feTurbulence generates a noise field, feDisplacementMap
   uses it to warp pixels, feGaussianBlur softens the result. Only those three
   primitives appear in that filter; none of them can raise a pixel's luminance
   (displacement moves pixels, blur redistributes them, neither brightens). The
   `scale` attribute driving the displacement's intensity is NOT animated by CSS (SVG
   filter primitive attributes aren't reliably CSS-transitionable); a small
   requestAnimationFrame loop in new.html.erb writes it directly, climbing from 0
   (a no-op, i.e. calm) to a fully liquified value over ~0.95s and stopping there,
   kicked the instant body.door-angry is set, so a calm visit that never triggers
   rejection never melts anything and the melted end-state is terminal.

   opacity and transform still animate here via a normal CSS transition, same
   flash-safety logic as everywhere else in this file: opacity only ever decreases
   (here, to 0, fully gone), and transform only moves/scales what's rendered. The
   transform is a downward drip (grow slightly taller, narrow a touch, slide down a
   little from the top edge) rather than the shrink-and-recede used before, to read as
   melting rather than retreating. Restrained on purpose (operator feedback: the first
   pass liquified too violently and dripped past the panel's bottom edge): the
   displacement peak and the drip distance are both dialed back, and `overflow: hidden`
   on the panel (below) hard-contains whatever's left so nothing can render outside the
   welcome panel's own box regardless of how the numbers are tuned later. */
body.door-angry .door-welcome h1,
body.door-angry .door-welcome .subtitle,
body.door-angry .door-welcome p {
    filter: url(#door-melt);
    opacity: 0;
    transform: scaleY(1.15) scaleX(0.97) translateY(14px);
    transform-origin: 50% 0%;
    /* !important: a pre-existing `h1, .ithildin, .ds-ithildin { transition: none
       !important; }` rule further down (under `(hover: none), (pointer: coarse)`,
       meant to kill the unrelated h1 hover-glow crossfade on touch devices) would
       otherwise also silently kill this transition for h1 specifically (not
       .subtitle/p, which aren't in that rule's selector) on touch/coarse-pointer
       devices, since its `!important` beats normal-weight rules regardless of
       specificity. Match its weight so it animates consistently for all three elements
       everywhere except prefers-reduced-motion, below. Duration matches the SVG melt's
       ~0.95s so the drip and the liquify complete together; trimmed down from an
       earlier 1.6s per operator feedback wanting the whole sequence snappier. */
    transition: opacity 0.95s ease-in, transform 0.95s ease-in !important;
}
/* Hard containment: the melt (filter displacement + the drip transform above) must
   never paint outside the welcome panel. clip-path (the chiseled bevel, set on every
   .crystal-panel) already clips most of this, but overflow: hidden is the explicit,
   well-supported backstop for filtered/transformed descendant content specifically.
   Scoped to the angry state only; the calm panel never needed clipping. */
body.door-angry .door-welcome {
    overflow: hidden;
}
@media (prefers-reduced-motion: reduce) {
    body.door-angry .door-welcome h1,
    body.door-angry .door-welcome .subtitle,
    body.door-angry .door-welcome p {
        transition: none !important;
    }
}

/* One voice, not two: a server-rendered rejection (registrations#create re-rendering
   :new with flash[:alert] set) sets body.door-angry from ERB (see new.html.erb) the
   same way the client-side bad-code check does. Fold its flash box away entirely
   rather than leaving a second, differently-worded, differently-styled error message
   on an angry page; the panel's own rejection-notice copy already carries the message.
   Scoped to `body.door-angry`, which registrations/new.html.erb is the only template
   that ever sets, so this can never hide a flash anywhere else on the site, and only
   the danger/error alert is touched, never `.alert-success` notices. */
body.door-angry .alert.alert-danger {
    display: none;
}

.alert-dismissible { position: relative; padding-right: 3rem; }
.btn-close {
    position: absolute; right: 0.55rem; top: 50%; transform: translateY(-50%);
    display: grid; place-items: center; width: 2.2rem; height: 2.2rem;
    background: none; border: none; color: inherit; font-size: 1.3rem; cursor: pointer; opacity: 0.72;
    clip-path: none; box-shadow: none; padding: 0;
}
.btn-close:hover { opacity: 1; }
.btn-close:focus-visible { opacity: 1; outline: 1px solid currentColor; outline-offset: -0.25rem; }
.btn-close::before { content: '\00d7'; }

/* One app-owned confirmation surface for all Turbo destructive actions. */
.app-confirm-dialog {
    width: min(28rem, calc(100vw - 2rem));
    margin: auto;
    padding: 0;
    color: var(--fog);
    background: transparent;
    border: 0;
}
.app-confirm-dialog::backdrop {
    background: rgba(4, 7, 5, 0.76);
    backdrop-filter: blur(3px);
}
.app-confirm-dialog-panel {
    padding: 1.4rem 1.5rem 1.3rem;
    background: linear-gradient(165deg, var(--basalt-lit), var(--basalt-slab));
    box-shadow: inset 0 0 0 1px rgba(75,186,219,0.28), 0 24px 64px rgba(0,0,0,0.7);
    clip-path: var(--cleft);
}
.app-confirm-dialog-panel h2,
.app-confirm-dialog-panel p {
    margin-top: 0;
}
.app-confirm-dialog-panel h2 {
    margin-bottom: 0.8rem;
    color: var(--silver-lit);
    font-size: 1.35rem;
}
.app-confirm-kicker {
    margin-bottom: 0.25rem;
    color: var(--lichen);
    font-size: 0.7rem;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.app-confirm-dialog.is-danger .app-confirm-kicker { color: var(--cedar); }
.app-confirm-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.6rem;
    margin-top: 1.25rem;
}

/* Tables: data as steel on stone. */
.data-table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.data-table th, .data-table td {
    padding: 0.75rem 1rem;
    text-align: left;
    border-bottom: 1px solid var(--moss-deep);
    border-bottom: 1px solid color-mix(in oklab, var(--moss-deep) calc((1 - var(--presence)) * 100%), var(--moss-live) calc(var(--presence) * 100%));
}
.data-table th { color: var(--lichen); font-weight: 600; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.06em; }
.data-table tbody tr:hover { background: rgba(48,82,59,0.2); }
.data-table code { font-size: 1rem; }
.invite-code-new { background: rgba(75,186,219,0.12); box-shadow: inset 0 0 0 1px rgba(75,186,219,0.3); }
.invite-code-new-badge { color: var(--glow); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.06em; margin-left: 0.5rem; }
.btn-small { padding: 0.25rem 0.6rem; font-size: 0.8rem; margin-left: 0.5rem; }

/* Presence consent (Profile and the pool page): one member per row, actions trailing. */
.presence-consent section + section { margin-top: 1.5rem; }
.presence-consent-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.presence-consent-list li { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; padding: 0.45rem 0; border-bottom: 1px solid rgba(221, 230, 240, 0.08); }
.presence-consent-list li form { display: inline; }
.presence-consent-list .btn-small { margin-left: 0; }
.presence-consent-list li > .text-muted { font-size: 0.85rem; }
.presence-consent-list li > .presence-consent-note { flex-basis: 100%; }
.presence-consent-add { display: flex; flex-wrap: wrap; align-items: end; gap: 0.5rem; margin-bottom: 1rem; }
.presence-consent-add label { flex-basis: 100%; }
.presence-consent-add select { flex: 1 1 12rem; width: auto; }

/* Party size: "People, including you" with -/+ (event page and calendar rail). */
.party-stepper label { display: block; margin-bottom: 0.3rem; color: var(--lichen); font-size: 0.9rem; }
.party-stepper-control { display: grid; grid-template-columns: 2.75rem minmax(3.5rem, 6rem) 2.75rem; gap: 0.4rem; }
.party-stepper-control .btn { width: auto; padding: 0; font-size: 1.25rem; line-height: 1; }
.party-stepper-control input { text-align: center; -moz-appearance: textfield; appearance: textfield; }
.party-stepper-control input::-webkit-inner-spin-button,
.party-stepper-control input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }

/* Hero Grid */
.hero-grid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 1rem; margin-top: 1.5rem; }
.hero-grid > div { text-align: center; }

/* Utility */
.text-center { text-align: center; }
.mt-1 { margin-top: 0.5rem; } .mt-2 { margin-top: 1rem; }
.mb-1 { margin-bottom: 0.5rem; } .mb-2 { margin-bottom: 1rem; }

/* Presence, not gate: full legibility for reduced-motion and no-hover. */
@media (prefers-reduced-motion: reduce) {
    h1, .ithildin, .ds-ithildin { transition: none !important; }
    * { animation-duration: 0.001s !important; }
}
@media (hover: none), (pointer: coarse) {
    h1, .ithildin, .ds-ithildin { transition: none !important; }
}

@media (max-width: 768px) {
    h1 { font-size: 1.9rem; letter-spacing: 0.1em; }
    h2 { font-size: 1.35rem; }
    .crystal-panel { padding: 1.5rem 1.4rem; }
    .content-wrapper { padding: 6rem 1rem 5rem 1rem; }
    .hero-grid { grid-template-columns: 1fr; }
}

.event-danger-zone {
    margin-top: 1.5rem;
    padding-top: 1.25rem;
    border-top: 1px solid rgba(255, 138, 128, 0.22);
    color: var(--fog-dim);
    font-size: 0.85rem;
}

.event-danger-zone summary {
    cursor: pointer;
    color: var(--fog);
}

.event-danger-zone .subtitle {
    margin: 0.5rem 0 0.75rem;
}
