/* Harmonia Wisdom — "The Quiet Museum" home page (dark-only by brand design).
   Brand hexes mirror the tvOS Color+Brand.swift source (see README). */

:root {
    --void: #0B0812;
    --void-top: #1A0B2E;
    --void-bottom: #050208;
    --violet: #7F13EC;
    --violet-glow: #9D4EDD;
    /* Violet for TEXT and focus rings: #9D4EDD falls below 4.5:1 on the glow;
       #B58AF0 holds >= 5.6:1 on the worst ground (same token as the legal pages). */
    --violet-text: #B58AF0;
    --gold: #D4A95A;
    --glass: rgba(30, 27, 38, 0.55);
    --line: rgba(255, 255, 255, 0.12);
    --t95: rgba(255, 255, 255, 0.95);
    --t70: rgba(255, 255, 255, 0.74);
    /* Quietest text. 0.45 measured ~4.6:1 on bare void and dropped below AA on glass
       cards; 0.62 keeps >= 6:1 on both. */
    --t55: rgba(255, 255, 255, 0.62);
    --serif: ui-serif, "New York", Georgia, "Times New Roman", serif;
    --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --max: 1080px;
    color-scheme: dark;
}

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

/* html carries the base colour so no canvas area can ever flash white. */
html { scroll-behavior: smooth; overflow-x: clip; background: #0B0812; }

body {
    /* No background-attachment:fixed: it forces full repaints and is broken on iOS. */
    background: linear-gradient(180deg, var(--void-top) 0%, var(--void) 22%, var(--void-bottom) 100%) no-repeat, var(--void);
    background-color: var(--void);
    color: var(--t95);
    font-family: var(--sans);
    font-size: 1.0625rem;
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    /* clip, not hidden: overflow-x:hidden would make body a scroll container and
       silently disable position:sticky on the header. */
    overflow-x: clip;
}

h1, h2, h3, .lede, figcaption { font-family: var(--serif); }

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

a { color: var(--violet-text); text-decoration: underline; text-decoration-color: rgba(181, 138, 240, 0.4); text-underline-offset: 3px; }
a:hover { text-decoration-color: currentColor; }

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

.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;
}

/* An author display rule must never beat the hidden attribute (the full-screen
   button is hidden where the Fullscreen API is missing). */
[hidden] { display: none !important; }
main:focus { outline: none; }   /* focused only by the skip link */

.skip-link {
    position: absolute; inset-inline-start: 1rem; top: -4rem; z-index: 2000;
    background: var(--void-top); color: var(--t95); padding: 0.7rem 1rem;
    border: 1px solid var(--violet-text); border-radius: 12px;
}
.skip-link:focus { top: 1rem; }

/* ── header — glass pill ─────────────────────────────── */
.site-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; flex-wrap: wrap;
    max-width: var(--max); margin: 2rem auto 0; padding: 0.8rem 1.5rem;
    background: linear-gradient(180deg, rgba(26, 11, 46, 0.75), rgba(15, 5, 30, 0.6));
    backdrop-filter: blur(26px) saturate(150%);
    -webkit-backdrop-filter: blur(26px) saturate(150%);
    border: 1px solid var(--line); border-radius: 35px;
    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.08);
    position: sticky; top: 0.9rem; z-index: 1000;
}
.brand {
    display: flex; align-items: center; gap: 0.6rem; min-height: 44px;
    font-size: 1.15rem; color: var(--t95); font-weight: 600;
    letter-spacing: 0.02em; text-decoration: none;
}
.brand img { border-radius: 8px; }
.site-head nav { display: flex; align-items: center; justify-content: center; gap: 0.4rem 1.2rem; flex-wrap: wrap; flex: 1 1 auto; }
.site-head nav a {
    display: inline-flex; align-items: center; min-height: 44px;
    color: var(--t70); font-size: 0.9rem; text-transform: uppercase; letter-spacing: 1px;
    text-decoration: none; transition: color 0.3s;
}
.site-head nav a:hover { color: var(--t95); }

.nav-toggle {
    display: none;
    flex-direction: column; justify-content: center; gap: 5px;
    width: 44px; height: 44px; padding: 0 11px;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--line); border-radius: 14px;
    cursor: pointer;
}
.nav-toggle span { display: block; height: 2px; border-radius: 2px; background: var(--t95); transition: transform 0.25s ease, opacity 0.2s ease; }
.nav-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ── language switcher & header actions ───────────────── */
.site-head-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    /* Between ~700 and ~930px the nav no longer fits beside the brand and this block wraps
       to a second row. Without an auto margin it then sat at the LEFT edge, and the menu
       (anchored to the picker's right edge) opened 40px off the left of the screen. The
       margin alone would also pull the nav away from the centre on a one-row header, so
       the nav takes the free space itself (below) and the margin only ever acts on a wrap. */
    margin-inline-start: auto;
}
.lang-picker {
    position: relative;
    display: inline-block;
}
.lang-picker summary {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    min-height: 44px;
    padding-inline: 0.75rem;
    color: var(--t70);
    font-size: 0.88rem;
    cursor: pointer;
    list-style: none;
    border-radius: 999px;
    transition: color 0.2s, background 0.2s;
    user-select: none;
}
.lang-picker summary::-webkit-details-marker {
    display: none;
}
.lang-picker summary::after {
    content: "▾";
    font-size: 0.7rem;
    opacity: 0.7;
    margin-inline-start: 0.2rem;
}
.lang-picker[open] summary::after {
    content: "▴";
}
.lang-picker summary:hover,
.lang-picker[open] summary {
    color: var(--t95);
    background: rgba(255, 255, 255, 0.06);
}
.lang-picker .lang-menu {
    position: absolute;
    top: calc(100% + 0.5rem);
    inset-inline-end: 0;
    min-width: 150px;
    max-height: min(380px, 65vh);
    overflow-y: auto;
    background: #140B22;
    border: 1px solid var(--line);
    border-radius: 16px;
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(127, 19, 236, 0.15);
    padding: 0.4rem;
    display: flex;
    flex-direction: column;
    gap: 2px;
    z-index: 1050;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
}
.lang-picker .lang-menu a {
    display: flex;
    align-items: center;
    min-height: 40px;
    padding: 0.4rem 0.8rem;
    color: var(--t70);
    font-size: 0.88rem;
    text-decoration: none;
    border-radius: 8px;
    white-space: nowrap;
    transition: background 0.15s, color 0.15s;
}
.lang-picker .lang-menu a:hover {
    background: rgba(255, 255, 255, 0.08);
    color: var(--t95);
}
.lang-picker .lang-menu a[aria-current="page"] {
    color: var(--violet-text);
    font-weight: 600;
    background: rgba(127, 19, 236, 0.15);
}

/* ── hero ───────────────────────────────────────────── */
.hero { position: relative; padding: 4.5rem 1.5rem 5rem; }
.glow { position: absolute; inset: 0; overflow: hidden; z-index: -1; pointer-events: none; }
.glow::before {
    content: ""; position: absolute;
    width: 60rem; height: 60rem; border-radius: 50%;
    left: 50%; top: -18rem; transform: translateX(-62%);
    background: radial-gradient(circle, rgba(127, 19, 236, 0.20) 0%, rgba(127, 19, 236, 0.07) 40%, transparent 65%);
    animation: drift 30s ease-in-out infinite alternate;
}
@keyframes drift {
    from { transform: translateX(-70%) translateY(0); }
    to   { transform: translateX(-45%) translateY(3rem); }
}
.hero-inner {
    max-width: var(--max); margin: 0 auto;
    display: grid; grid-template-columns: 1.25fr 0.75fr;
    gap: 3rem; align-items: center;
}
/* Two-column hero at full width: the nav pill stops at --max and its logo sits 1.5rem inside
   the pill's border, so the hero is 3rem narrower to line the heading up with the logo, not
   the border. The copy column takes a larger share so the heading keeps its two lines. Below
   --max the pill runs edge to edge and both already align. */
@media (min-width: 1080px) {
    .hero-inner { max-width: calc(var(--max) - 3rem); grid-template-columns: 1.35fr 0.65fr; }
}
.eyebrow { color: var(--gold); font-size: 0.8rem; letter-spacing: 0.22em; text-transform: uppercase; margin-bottom: 1.2rem; }
h1 {
    font-size: clamp(2.4rem, 6vw, 4.4rem);
    line-height: 1.08; font-weight: 600; letter-spacing: -0.01em;
    margin-bottom: 1.4rem; text-wrap: balance;
}
.lede { color: var(--t70); font-size: clamp(1.1rem, 2.2vw, 1.35rem); line-height: 1.55; max-width: 34em; margin-bottom: 2rem; }

/* A grid or flex child's min-width is `auto` = its min-content width. Without this a single
   unbreakable run in the copy column widens the whole column past the screen. */
.hero-copy { min-width: 0; }
/* Last resort on every text block of the hero: a word that cannot fit breaks instead of
   poking out of the viewport. Does not alter wrapping of anything that already fits. */
.eyebrow, h1, .lede { overflow-wrap: break-word; }

/* A phrase the translator glued together so a heading never ends on a lone short word.
   An inline-block is atomic: it moves to the next line whole, like the &nbsp; run it
   replaces, but its shrink-to-fit width is capped at the line (max-width), so a phrase
   wider than the column wraps inside itself instead of widening the column or painting
   over its neighbour. "una pratica quotidiana." at 38px is wider than a phone, and
   "ежедневной практикой." at 70px is wider than the desktop copy column. */
.nb { display: inline-block; max-width: 100%; }

/* Store status: plain text, deliberately NOT badge-shaped and not links. */
.status-list { list-style: none; display: grid; gap: 0.35rem; margin-bottom: 1.1rem; max-width: 30rem; }
.status-list li { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0 1rem; padding: 0.35rem 0; border-bottom: 1px solid var(--line); color: var(--t70); font-size: 0.95rem; }
.status-list li:last-child { border-bottom: 0; }
.status-list .plat { color: var(--t95); font-weight: 600; }
.fineprint { color: var(--t55); font-size: 0.88rem; max-width: 38em; }

.hero-shot { justify-self: center; text-align: center; }
.hero-shot .phone { margin-inline: auto; }
.phone {
    position: relative;
    width: min(280px, 70vw);
    border-radius: 34px; overflow: hidden;
    border: 1px solid var(--line);
    box-shadow: 0 40px 90px rgba(0, 0, 0, 0.65), 0 0 70px rgba(127, 19, 236, 0.12);
    background: var(--glass);
}
.phone img { width: 100%; height: auto; }
/* iPhone notch: the screenshots' status bars split around the centre, so it covers nothing. */
.phone::before {
    content: ""; position: absolute; top: -1px; left: 50%; transform: translateX(-50%);
    width: 46%; height: 3.4%;
    background: #06040a;
    border-radius: 0 0 16px 16px;
    z-index: 2; pointer-events: none;
}
figcaption { color: var(--t55); font-size: 0.95rem; font-style: italic; margin-top: 1rem; }

/* ── collection stats ───────────────────────────────── */
.collection { padding: 1rem 1.5rem 3rem; }
.stats {
    max-width: var(--max); margin: 0 auto;
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 1px;
    background: var(--line); border: 1px solid var(--line); border-radius: 18px;
    overflow: hidden;
}
.stats > div { background: rgba(11, 8, 18, 0.92); padding: 1.6rem 1rem; text-align: center; display: flex; flex-direction: column-reverse; }
.stats dt { color: var(--t55); font-size: 0.78rem; letter-spacing: 0.14em; text-transform: uppercase; }
.stats dd { font-family: var(--serif); font-size: clamp(1.6rem, 3.4vw, 2.4rem); color: var(--t95); margin-bottom: 0.3rem; }

/* ── sections ───────────────────────────────────────── */
section { padding: 4.5rem 1.5rem; }
.practice, .platforms, .creed, .door, .gallery, .constellation { max-width: var(--max); margin: 0 auto; scroll-margin-top: 6rem; }
h2 { font-size: clamp(1.9rem, 4.4vw, 3rem); font-weight: 600; line-height: 1.15; margin-bottom: 1rem; text-wrap: balance; }
.section-lede { color: var(--t70); font-size: 1.15rem; max-width: 38em; margin-bottom: 2.6rem; }

.exhibits, .rooms { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; list-style: none; }
.rooms { grid-template-columns: repeat(4, 1fr); }
.card {
    background: var(--glass); border: 1px solid var(--line);
    border-radius: 20px; padding: 1.6rem;
    position: relative; overflow: hidden;
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.card::before {
    content: ""; position: absolute; top: 0; left: 8%; right: 8%; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,0.35), transparent);
}
.card h3 { font-size: 1.22rem; margin-bottom: 0.6rem; }
.card p { color: var(--t70); font-size: 0.96rem; }
.tag {
    display: inline-block; margin-bottom: 0.7rem;
    font-family: var(--sans); font-size: 0.7rem; letter-spacing: 0.12em;
    text-transform: uppercase; color: var(--gold);
    border: 1px solid rgba(212, 169, 90, 0.4); border-radius: 99px;
    padding: 0.15rem 0.6rem;
}

.more { margin-top: 2.6rem; border: 1px solid var(--line); border-radius: 16px; }
.more summary {
    cursor: pointer; padding: 1.1rem 1.4rem; min-height: 44px;
    font-family: var(--serif); font-size: 1.1rem; color: var(--t95);
    list-style-position: inside; border-radius: 16px;
}
.more[open] summary { border-bottom: 1px solid var(--line); border-radius: 16px 16px 0 0; }
.more ul { padding: 1.2rem 1.6rem 1.4rem 2.4rem; columns: 2; column-gap: 2.5rem; }
.more li { color: var(--t70); font-size: 0.95rem; margin-bottom: 0.7rem; break-inside: avoid; }
.more strong { color: var(--t95); }

/* ── creed ──────────────────────────────────────────── */
.creed-cols { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2.2rem; margin-top: 1.4rem; }
.creed h3 { font-size: 1.2rem; margin-bottom: 0.6rem; }
.creed h3::before { content: "— "; color: var(--gold); }
.creed p { color: var(--t70); font-size: 0.97rem; }

/* ── door / contact ─────────────────────────────────── */
.door { text-align: center; }
.door .section-lede { margin: 0 auto 1.6rem; }
.door .status-list { margin: 0 auto 2rem; text-align: left; }
.contact-line { font-size: 1.1rem; }
.contact-line a { display: inline-block; padding: 0.6rem 0.2rem; }

/* ── footer ─────────────────────────────────────────── */
.site-foot { border-top: 1px solid var(--line); padding: 2.4rem 1.5rem 3rem; text-align: center; color: var(--t55); font-size: 0.85rem; }
.foot-links { display: flex; flex-wrap: wrap; gap: 0 1.4rem; justify-content: center; margin-bottom: 0.8rem; }
.foot-links a { display: inline-flex; align-items: center; min-height: 44px; color: var(--t70); }
.foot-id { margin-bottom: 0.3rem; overflow-wrap: anywhere; }
.tm { max-width: 46rem; margin: 1.2rem auto 0; font-size: 0.78rem; line-height: 1.6; }

/* ── gallery: screenshot carousel ───────────────────── */
/* position: relative so the arrow pills can be absolutely placed over the stage. */
.carousel { position: relative; margin-top: 1.5rem; --item-w: min(250px, 62vw); overflow-x: clip; }
.carousel-stage {
    perspective: 1600px;
    height: calc(var(--item-w) * 2.35);
    display: grid; place-items: center;
    /* pan-y alone does NOT permit pinch: a zoom starting on this element gets its
       zoom handling suppressed. Both stages are large, so that covered much of the
       page. pinch-zoom restores it, and never disable zoom in the viewport meta. */
    touch-action: pan-y pinch-zoom;
    cursor: grab;
    -webkit-user-select: none; user-select: none;
    border-radius: 20px;
}
.carousel-stage.dragging { cursor: grabbing; }
.carousel-ring {
    position: relative; list-style: none;
    width: var(--item-w); height: calc(var(--item-w) * 2.166);
    transform-style: preserve-3d;
    transition: transform 0.75s cubic-bezier(0.22, 1, 0.36, 1);
}
.carousel-item {
    position: absolute; inset: 0;
    width: var(--item-w); margin: 0;
    filter: brightness(0.38) saturate(0.75);
    transition: filter 0.6s ease;
}
.carousel-item figure, .carousel-item .phone { width: 100%; height: 100%; }
.carousel-item.front { filter: none; }
.carousel-item img { pointer-events: none; width: 100%; height: 100%; object-fit: cover; }
.js .carousel-item figcaption { display: none; }   /* painted once, in the shared caption */
.slide-title { display: block; font-style: normal; color: var(--gold); }

/* Caption only: the arrows moved out to sit beside the stage. */
.carousel-nav { display: flex; justify-content: center; margin-top: 1.6rem; }
.car-btn {
    flex: 0 0 auto;
    width: 48px; height: 48px; border-radius: 50%;
    border: 1px solid var(--line); background: var(--glass); color: var(--t95);
    font-size: 1.1rem; cursor: pointer;
    transition: background 0.2s ease;
    /* Centre the arrow GEOMETRICALLY, not by font metrics. A button's default text
       centring comes from line-height:normal plus the resolved font's ascent/descent,
       so the same markup sat centred on iOS and visibly low in Chrome on Android,
       which falls back to a different face. Flex centring plus line-height:1 removes
       the font from the calculation entirely. Reported on a Galaxy A32, 2026-09-16. */
    display: inline-flex; align-items: center; justify-content: center;
    line-height: 1;
}
.car-btn:hover { background: rgba(127, 19, 236, 0.3); }

/* Arrow pills, overlaid on the stage: dragging a 3D ring is fiddly on a phone, so
   the buttons sit where the thumb already is. Positive insets on purpose — the
   carousel clips its own overflow, and a negative offset would also put the left
   pill in Safari's back-swipe edge zone. No backdrop-filter here by design. */
.car-pill {
    position: absolute; z-index: 3;
    top: calc(var(--item-w) * 1.175);          /* half the stage's height */
    transform: translateY(-50%);
    background: rgba(24, 18, 34, 0.86);
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45);
}
/* Measured from the RING, not from the carousel box. The section is up to 1080px wide
   while the ring stays --item-w, so a fixed inset would strand the arrows hundreds of
   pixels from the artwork they control on a desktop. 3.5rem clears the widest pill and
   leaves 8-12px of air; the max() keeps them on-screen when the two widths converge. */
.car-pill-prev { left:  max(0.5rem, calc(50% - var(--item-w) / 2 - 3.5rem)); }
.car-pill-next { right: max(0.5rem, calc(50% - var(--item-w) / 2 - 3.5rem)); }
.carousel-caption {
    width: min(34rem, 100%); min-height: 8rem; text-align: center;
    background: var(--glass); border: 1px solid var(--line); border-radius: 18px;
    padding: 1rem 1.4rem;
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
}
.carousel-caption h3 { font-family: var(--serif); font-size: 1.18rem; margin-bottom: 0.35rem; color: var(--gold); }
.carousel-caption p { color: var(--t70); font-size: 0.93rem; line-height: 1.55; }
.carousel-caption .car-count { color: var(--t55); font-size: 0.8rem; letter-spacing: 0.08em; margin-top: 0.4rem; }
.carousel-caption h3, .carousel-caption p { transition: opacity 0.2s ease; }
.carousel-caption.swap h3, .carousel-caption.swap p { opacity: 0; }

/* No JS: a plain, scrollable strip of screenshots with their captions. */
html:not(.js) .carousel-stage { perspective: none; height: auto; display: block; overflow-x: auto; cursor: auto; padding-bottom: 1rem; }
html:not(.js) .carousel-ring { width: auto; height: auto; display: flex; gap: 1.2rem; transform: none; }
html:not(.js) .carousel-item { position: static; flex: 0 0 var(--item-w); filter: none; }
html:not(.js) .carousel-item .phone { height: auto; }
html:not(.js) .needs-js { display: none; }

/* ── constellation of influence ─────────────────────── */
.const-wrap { display: grid; grid-template-columns: 1.5fr 1fr; gap: 1.2rem; margin-top: 1.4rem; align-items: stretch; }
.const-stage {
    position: relative;
    border: 1px solid var(--line); border-radius: 20px;
    background:
        radial-gradient(ellipse at 30% 20%, rgba(127, 19, 236, 0.14), transparent 55%),
        radial-gradient(ellipse at 75% 80%, rgba(212, 169, 90, 0.06), transparent 60%),
        rgba(5, 2, 8, 0.75);
    overflow: hidden;
    min-height: 30rem;
    touch-action: pan-y pinch-zoom;   /* pinch-zoom is required; see .carousel-stage */
}
html:not(.js) .const-stage, html:not(.js) .school-chips { display: none; }
html:not(.js) .const-wrap { grid-template-columns: 1fr; }
#const-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; cursor: grab; }
#const-canvas.dragging { cursor: grabbing; }
.const-full {
    position: absolute; top: 0.8rem; right: 0.8rem;
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    background: var(--glass); color: var(--t95);
    border: 1px solid var(--line); border-radius: 12px;
    cursor: pointer;
}
.const-full:hover { border-color: var(--violet-text); }
.const-wrap:fullscreen { background: var(--void); padding: 1.2rem; margin: 0; max-width: none; overflow: auto; }
.const-wrap:fullscreen .const-stage { min-height: calc(100vh - 2.4rem); }
.const-wrap:fullscreen .const-panel { max-height: calc(100vh - 2.4rem); }
.const-hint {
    position: absolute; left: 0; right: 0; bottom: 0.7rem; text-align: center;
    color: var(--t55); font-size: 0.8rem; letter-spacing: 0.08em;
    pointer-events: none; transition: opacity 0.6s ease;
}
.const-hint.hidden-hint { opacity: 0; }
.premium-note { color: var(--t55); font-size: 0.92rem; margin-top: 1.4rem; }

.school-chips { display: flex; justify-content: center; flex-wrap: wrap; gap: 0.6rem; margin: 0 auto 1.6rem; }
.school-chip {
    display: inline-flex; align-items: center; gap: 0.45rem; min-height: 44px;
    background: var(--glass); color: var(--t70);
    border: 1px solid var(--line); border-radius: 22px;
    padding: 0.45rem 1rem; font-family: var(--sans); font-size: 0.86rem;
    letter-spacing: 0.03em; cursor: pointer;
    transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}
.school-chip i { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.school-chip:hover { color: var(--t95); border-color: var(--violet-text); }
.school-chip[aria-current="true"] { color: var(--t95); background: rgba(127, 19, 236, 0.28); border-color: var(--violet-text); }

.const-panel {
    border: 1px solid var(--line); border-radius: 20px;
    background: var(--glass);
    padding: 1.5rem 1.5rem 0;
    max-height: 34rem; overflow: hidden;
    display: flex; flex-direction: column;
}
.const-panel > .needs-js { display: flex; flex-direction: column; flex: 1; min-height: 0; padding-bottom: 1rem; }
.const-pick-label { color: var(--t70); font-size: 0.85rem; margin-bottom: 0.3rem; }
.const-pick {
    min-height: 44px; margin-bottom: 1rem; padding: 0 0.8rem;
    background: rgba(11, 8, 18, 0.85); color: var(--t95);
    border: 1px solid var(--line); border-radius: 12px;
    font-family: var(--sans); font-size: 1rem;
}
.const-kicker { color: var(--gold); font-size: 0.74rem; letter-spacing: 0.2em; text-transform: uppercase; margin-bottom: 0.4rem; }
.const-panel h3 { font-family: var(--serif); font-size: 1.7rem; line-height: 1.15; }
.const-meta { color: var(--t55); font-size: 0.88rem; margin: 0.25rem 0 1rem; }
.const-list { list-style: none; overflow-y: auto; flex: 1; min-height: 0; overscroll-behavior: contain; }
.const-list li { padding: 0.6rem 0; border-top: 1px solid var(--line); }
.const-list button {
    min-height: 44px; background: none; border: none; padding: 0 0.1rem; cursor: pointer;
    color: var(--t95); font-family: var(--serif); font-size: 1.02rem; text-align: left;
    text-decoration: underline; text-decoration-color: rgba(181, 138, 240, 0.4); text-underline-offset: 3px;
}
.const-list button:hover { color: var(--violet-text); }
.const-type {
    font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
    color: var(--gold); border: 1px solid rgba(212, 169, 90, 0.35);
    border-radius: 99px; padding: 0.1rem 0.5rem; margin-left: 0.5rem;
    vertical-align: middle; white-space: nowrap;
}
.const-list p { color: var(--t70); font-size: 0.9rem; line-height: 1.55; margin-top: 0.2rem; }
.nojs-note { color: var(--t70); font-size: 0.95rem; padding-bottom: 1.5rem; }

/* ── reveals: hidden only when JS is confirmed running ── */
.js .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.6s ease, transform 0.6s ease; }
.js .reveal.in { opacity: 1; transform: none; }

/* ── reduced motion: nothing animates, the carousel becomes a flat cross-cut ── */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    .js .reveal { opacity: 1; transform: none; transition: none; }
    .glow::before { animation: none; }
    .nav-toggle span, .car-btn, .school-chip, .const-hint, .carousel-caption h3, .carousel-caption p { transition: none; }
    .js .carousel-stage { perspective: none; }
    .js .carousel-ring { transform: none !important; transition: none; }
    .js .carousel-item { transform: none !important; transition: none; filter: none; visibility: hidden; }
    .js .carousel-item.front { visibility: visible; }
}

/* Print: content still hidden behind a scroll reveal must print. */
@media print {
    .js .reveal { opacity: 1; transform: none; }
}

/* ── responsive ─────────────────────────────────────── */
@media (max-width: 900px) {
    .hero-inner { grid-template-columns: minmax(0, 1fr); text-align: center; }
    .hero-copy .lede, .fineprint, .hero-copy .status-list { margin-left: auto; margin-right: auto; }
    .hero-copy .status-list { text-align: left; }
    .exhibits { grid-template-columns: repeat(2, 1fr); }
    .rooms { grid-template-columns: repeat(2, 1fr); }
    .creed-cols { grid-template-columns: minmax(0, 1fr); }
    .more ul { columns: 1; }
    .const-wrap { grid-template-columns: minmax(0, 1fr); }
    .const-stage { min-height: min(26rem, 105vw); }
    .const-panel { max-height: 30rem; }
}
/* Also keyed to HEIGHT, not width alone. A phone in landscape is ~844-932px wide, so a
   width-only query left it with the full word menu: brand + nav did not fit inside the
   padding, the flex row wrapped, and the header grew to 132px — 34% of a 390px-tall
   screen. Height is the scarce resource in landscape, so a short viewport gets the same
   compact treatment as a narrow one. Measured on the deployed preview, 2026-09-16. */
@media (max-width: 700px), (max-height: 500px) {
    .site-head { margin: 0.9rem 0.9rem 0; flex-wrap: nowrap; }
    .js .nav-toggle { display: inline-flex; }
    .js .site-head nav {
        display: none;
        position: absolute; left: 0; right: 0; top: calc(100% + 0.6rem);
        flex-direction: column; align-items: stretch; gap: 0;
        padding: 0.6rem;
        background: linear-gradient(180deg, rgba(26, 11, 46, 0.97), rgba(15, 5, 30, 0.95));
        border: 1px solid var(--line); border-radius: 22px;
        box-shadow: 0 24px 60px rgba(0, 0, 0, 0.55);
    }
    .js .site-head nav.open { display: flex; }
    .js .site-head nav a { padding: 0 1.1rem; border-radius: 14px; font-size: 0.95rem; }
    .js .site-head nav a:hover { background: rgba(127, 19, 236, 0.18); }
    /* Without JS the menu button would be dead: show the links, wrapped. */
    html:not(.js) .site-head { flex-wrap: wrap; position: static; }
    html:not(.js) .site-head nav { gap: 0 1rem; }
}
@media (max-width: 560px) {
    body { font-size: 1rem; }
    .site-head { padding: 0.5rem 0.9rem; }
    .hero { padding: 2.6rem 1.25rem 3.4rem; }
    .hero-inner { gap: 2.2rem; }
    .eyebrow { margin-bottom: 0.9rem; }
    .lede { margin-bottom: 1.6rem; }
    .phone { width: min(240px, 68vw); border-radius: 28px; }
    .exhibits, .rooms { grid-template-columns: minmax(0, 1fr); }
    .stats { grid-template-columns: repeat(2, 1fr); }
    .stats > div { padding: 1.15rem 0.6rem; }
    .stats dt { letter-spacing: 0.08em; }
    section { padding: 3rem 1.25rem; }
    .section-lede { font-size: 1.05rem; margin-bottom: 2rem; }
    .card { padding: 1.3rem; border-radius: 16px; }

    .carousel { --item-w: min(215px, 60vw); }
    .carousel-stage { perspective: 1100px; }
    .carousel-caption { min-height: 9rem; }
    /* Narrow screens: keep the pills clear of the phone artwork's edges. */
    /* 44px is the tap-target floor the rest of this page keeps; never shrink below it.
       The insets need no override here: they are computed from the ring's own width. */
    .car-pill { width: 44px; height: 44px; font-size: 1rem; }

    /* minmax(0, ...): a bare 1fr is minmax(auto, 1fr), so one long school name (nl, sv) widened
       the grid past a 320px screen. The name wraps inside its chip instead. */
    .school-chips { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .school-chip { justify-content: flex-start; text-align: left; line-height: 1.25; min-width: 0; overflow-wrap: anywhere; }

    .const-stage { min-height: min(24rem, 115vw); border-radius: 16px; }
    .const-panel { padding: 1.2rem 1.2rem 0; border-radius: 16px; }
    .const-panel h3 { font-size: 1.45rem; }
    /* The role pill ("insegnato da ...") is nowrap on desktop; in a 320px panel it is wider than
       the panel and the list scrolled sideways. Let it wrap; it keeps its rounded outline. */
    .const-type { white-space: normal; max-width: 100%; }

    .site-foot { padding: 2rem 1.25rem 2.6rem; }
}

/* Header on the narrowest phones. Brand + language picker + menu button is ~327px of
   content with a long language name ("Nederlands", "Português") and the header has only
   ~262-320px, so the menu button was pushed off the right edge. The picker is the
   flexible part: it gives up width and ellipsises its label (the full name stays in
   its aria-label and in the open menu). Nothing here applies above 400px, so the
   desktop and tablet header are untouched. */
@media (max-width: 400px) {
    .site-head { margin: 0.6rem 0.6rem 0; padding: 0.4rem 0.6rem; gap: 0.5rem; }
    .brand { font-size: 1.05rem; gap: 0.5rem; flex: 0 0 auto; }
    .site-head-actions { min-width: 0; gap: 0.25rem; }
    .lang-picker { min-width: 0; }
    .lang-picker summary {
        display: block; position: relative; max-width: 100%;
        padding-inline: 0.5rem 1.35rem; line-height: 44px;
        overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    /* The caret sits in the padding, so ellipsis never clips it. */
    .lang-picker summary::after {
        position: absolute; inset-inline-end: 0.5rem; top: 50%;
        transform: translateY(-50%); margin: 0;
    }
}
@media (max-width: 340px) {
    .brand img { display: none; }   /* decorative (alt=""); frees 40px for the picker */
}

/* ── touch devices: no backdrop blur ─────────────────── */
/* iOS Safari re-rasterizes every backdrop-filtered layer when the pinch scale changes.
   This page had twelve — a sticky blurred header, ten cards and the caption — which is
   enough for the tab to be killed and reloaded mid-zoom. Solid grounds read the same on
   a phone. NOT keyed to max-width alone: an iPhone in landscape is 844-932 CSS px, so a
   700px query would hand every blur back on the exact device that crashed. pointer:coarse
   catches phone landscape and touch tablets; desktop keeps its blur.
   Paired with the resize guards in script.js. See docs/UNFORGET.md — mitigated, not yet
   proven fixed; it needs a pinch on a real iPhone, portrait AND landscape. */
@media (max-width: 700px), (pointer: coarse) {
    .site-head {
        backdrop-filter: none; -webkit-backdrop-filter: none;
        background: linear-gradient(180deg, rgba(26, 11, 46, 0.97), rgba(15, 5, 30, 0.95));
    }
    .card, .carousel-caption {
        backdrop-filter: none; -webkit-backdrop-filter: none;
        background: rgba(26, 21, 36, 0.94);
    }
}
