/* =========================================================================
   App menu — the homepage's menu disc and pop-up, shared by Studio and the
   Wiki so both apps have it in the same corner. The disc is the last thing
   in each app's top bar (60px on a phone, 68px from 1000px, 16/24px from the
   right edge), and the panel pins to the screen under it, so the two apps
   put it at identical coordinates. The panel is always the site's dark
   glass, whatever theme the app is in.
   ========================================================================= */

/* until app-menu.js has built it, the slot's raw settings stay out of the bar */
[data-amenu]:not(.amenu) { display: none; }
.amenu { position: relative; flex: none; margin-left: 4px; }

/* dims the page behind the open menu; the disc and the panel sit above it */
.amenu__scrim { position: fixed; inset: 0; z-index: 39; background: rgba(0, 0, 0, .35); opacity: 0; pointer-events: none; transition: opacity .3s ease; }
.amenu__scrim.is-on { opacity: 1; pointer-events: auto; }
:root[data-theme="light"] .amenu__scrim { background: rgba(19, 15, 12, .2); }
@media (prefers-color-scheme: light) { :root:not([data-theme="dark"]) .amenu__scrim { background: rgba(19, 15, 12, .2); } }

.amenu__btn {
  position: relative;
  z-index: 41;
  /* carried across from the site's menu disc (view transition below) */
  view-transition-name: menu-disc;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: color-mix(in srgb, currentColor 8%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 6%, transparent);
  color: inherit;
  cursor: pointer;
  transition: background-color .25s cubic-bezier(0.16, 1, 0.3, 1), transform .18s cubic-bezier(0.16, 1, 0.3, 1);
}
.amenu__btn:hover { background: color-mix(in srgb, currentColor 12%, transparent); }
.amenu__btn:active { transform: scale(.92); }

/* On hover (mouse only), a small hint under the disc that the menu is
   also the way to the Wiki and Studio. Gone while the menu is open. */
@media (hover: hover) {
  .amenu__btn::after {
    content: "Wiki, Studio & more";
    position: absolute; top: calc(100% + 8px); right: 0;
    padding: 6px 10px; border-radius: 10px;
    background: #130F0C; color: #FFFFFF;
    box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12), 0 8px 20px -10px rgba(0, 0, 0, .5);
    font-size: 13px; line-height: 1.2; letter-spacing: 0; white-space: nowrap;
    pointer-events: none; opacity: 0; transform: translateY(-4px);
    transition: opacity .18s ease, transform .18s ease;
  }
  .amenu__btn:hover::after { opacity: 1; transform: none; transition-delay: .35s; }
  .amenu__btn[aria-expanded="true"]::after { opacity: 0; transition-delay: 0s; }
}
@media (prefers-reduced-motion: reduce) { .amenu__btn::after { transition: none; } }

/* three unequal rules, longest first — the homepage burger's mark */
.amenu__mark { display: grid; gap: 4px; width: 18px; }
.amenu__mark i {
  display: block;
  /* whole pixels: 2px rules, 6px apart, so the × closes exactly */
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transform-origin: center;
  transition: transform .3s cubic-bezier(0.16, 1, 0.3, 1), opacity .2s;
}
.amenu__mark i:nth-child(1) { width: 100%; }
.amenu__mark i:nth-child(2) { width: 72%; }
.amenu__mark i:nth-child(3) { width: 44%; }
.amenu__btn[aria-expanded="true"] .amenu__mark i:nth-child(1) { width: 100%; transform: translateY(6px) rotate(45deg); }
.amenu__btn[aria-expanded="true"] .amenu__mark i:nth-child(2) { opacity: 0; }
.amenu__btn[aria-expanded="true"] .amenu__mark i:nth-child(3) { width: 100%; transform: translateY(-6px) rotate(-45deg); }

.amenu__panel {
  /* dark glass in a dark theme, light glass in a light one (below); the app
     controls inside read these */
  --fg: #FFFFFF;
  --bg: #000000;
  --line: color-mix(in srgb, #FFFFFF 14%, transparent);
  --well: color-mix(in srgb, #FFFFFF 10%, transparent);
  --muted: color-mix(in srgb, #FFFFFF 62%, transparent);
  position: fixed;
  z-index: 40;
  right: 16px;
  top: calc(60px + env(safe-area-inset-top, 0px));
  width: min(280px, calc(100vw - 32px));
  max-height: calc(100dvh - 80px);
  overflow-y: auto;
  display: grid;
  padding: 12px;
  border-radius: 28px;
  color: var(--fg);
  background: color-mix(in srgb, #000000 94%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(1.25);
  backdrop-filter: blur(12px) saturate(1.25);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, #FFFFFF 10%, transparent),
    inset 0 1px 0 0 color-mix(in srgb, #FFFFFF 14%, transparent),
    0 18px 40px -20px rgba(0, 0, 0, .6);
  transform-origin: calc(100% - 20px) -20px;
  animation: amenuIn .5s cubic-bezier(.32, 1.28, .42, 1);
}
.amenu__panel[hidden] { display: none; }
/* Opens the way iOS 26 menus do, as the site's menu: grows out of the
   button that opened it — blurred while it stretches, sharp when it lands —
   and folds back into it on close (.is-closing, app-menu.js). */
@keyframes amenuIn {
  0% { transform: scale(.12, .06); border-radius: 60px; filter: blur(10px); opacity: .3; }
  45% { filter: blur(3px); opacity: 1; }
  100% { transform: none; filter: none; opacity: 1; }
}
@keyframes amenuOut { to { transform: scale(.12, .06); border-radius: 60px; filter: blur(10px); opacity: 0; } }
@keyframes amenuItems { from { opacity: 0; filter: blur(6px); transform: translateY(-4px); } }
.amenu__panel > * { animation: amenuItems .4s cubic-bezier(.2, .8, .2, 1) .08s both; }
.amenu__panel.is-closing { animation: amenuOut .22s cubic-bezier(.4, 0, .7, .2) both !important; }
@media (min-width: 1000px) {
  .amenu__panel { right: 24px; top: 68px; }
}

/* an app's own settings (Studio: guides, appearance) */
.amenu__extra { display: grid; padding: 8px 0; border-top: 1px solid var(--line); }
.amenu__extra:empty { display: none; }

.amenu__social { display: flex; align-items: center; gap: 4px; padding: 12px 4px 4px 12px; border-top: 1px solid var(--line); }
.amenu__follow { margin-right: auto; font-size: 15px; color: var(--muted); }
.amenu__social a { display: grid; place-content: center; width: 40px; height: 40px; border-radius: 999px; color: var(--fg); transition: background-color .2s; }
.amenu__social a:hover, .amenu__social a:focus-visible { background: var(--well); outline: none; }
.amenu__social svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.amenu__social svg .fill { fill: currentColor; stroke: none; }

@media (prefers-reduced-motion: reduce) {
  .amenu__panel, .amenu__panel > *, .amenu__panel.is-closing { animation: none !important; }
  .amenu__mark i { transition: none; }
}

/* ── Settings in the sidebar (desktop) ─────────────────────────────────── */
.asettings { display: none; }
@media (min-width: 1000px) {
  .asettings { display: block; position: absolute; left: 10px; right: 10px; bottom: 12px; }
}
.asettings__btn {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 10px 14px;
  border: 0; border-radius: 14px; background: transparent;
  color: var(--muted); font: inherit; font-size: 15px; letter-spacing: 0; text-align: left;
  cursor: pointer; transition: background-color .2s, color .2s;
}
.asettings__btn svg { width: 20px; height: 20px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; }
.asettings__btn:hover, .asettings__btn[aria-expanded="true"] { color: var(--fg); background: color-mix(in srgb, var(--fg) 8%, transparent); }
.asettings__pop {
  --fg: #FFFFFF; --bg: #000000;
  --line: color-mix(in srgb, #FFFFFF 14%, transparent);
  --well: color-mix(in srgb, #FFFFFF 10%, transparent);
  --muted: color-mix(in srgb, #FFFFFF 62%, transparent);
  position: absolute; left: 0; bottom: calc(100% + 8px);
  width: 300px; padding: 8px;
  border-radius: 22px; color: #FFFFFF;
  background: color-mix(in srgb, #000000 94%, transparent);
  -webkit-backdrop-filter: blur(12px) saturate(1.25); backdrop-filter: blur(12px) saturate(1.25);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #FFFFFF 10%, transparent), 0 18px 40px -20px rgba(0,0,0,.6);
  transform-origin: bottom left;
  animation: amenuIn .5s cubic-bezier(.32, 1.28, .42, 1);
  z-index: 40;
}
.asettings__pop[hidden] { display: none; }
.asettings__pop .amenu__extra { border-top: 0; padding: 0; }

/* the settings rows, for apps that don't style their own (the Wiki) */
.amenu__extra .menu__row { display: grid; gap: 10px; padding: 10px 12px 12px; }
.amenu__extra .menu__label { font-size: 15px; }
.amenu__extra .seg { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; width: 100%; padding: 4px; border-radius: 999px; background: var(--well); }
.amenu__extra .seg__btn { min-height: 32px; padding: 0 10px; border: 0; border-radius: 999px; background: transparent; color: var(--muted); font: inherit; font-size: 13.5px; cursor: pointer; transition: background-color .2s, color .2s; }
.amenu__extra .seg__btn[aria-checked="true"] { background: var(--fg); color: var(--bg); }
/* Appearance takes one row: the label on the left, a compact switch of three
   symbols (system, light, dark) on the right. Beats Studio's own row styles. */
.amenu__extra .menu__row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 8px 4px 8px 12px; }
.amenu__extra .menu__row .seg { display: flex; width: auto; gap: 2px; padding: 3px; border-radius: 999px; background: var(--well); }
.amenu__extra .menu__row .seg__btn { display: grid; place-items: center; width: 40px; min-height: 30px; padding: 0; }
.amenu__extra .seg__btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ── The menu's contents (same as the site's) ──────────────────────────
   Site, Wiki and Studio set large — the one you're in white with a dot, the
   others grey — then Contact · Shop · Donate as one line. */
.amenu__words { display: grid; padding: 4px 8px 0 12px; }
.amenu__word { display: flex; align-items: center; gap: 10px; padding: 2px 0; font-size: 34px; line-height: 1.12; letter-spacing: -0.04em; text-decoration: none; color: color-mix(in srgb, var(--fg) 40%, transparent); transition: color .2s; }
.amenu__word:hover, .amenu__word:focus-visible { color: var(--fg); outline: none; }
.amenu__word[aria-current="page"] { color: var(--fg); }
.amenu__word[aria-current="page"]::after { content: ""; width: 8px; height: 8px; border-radius: 50%; background: var(--fg);
  /* centred on the lowercase letters, not the line box (which the face's
     tall ascent pushes up): a tenth of the type size down */
  transform: translateY(.1em); }
.amenu__acts { display: flex; flex-wrap: wrap; gap: 6px 18px; padding: 16px 8px 12px 12px; font-size: 15px; }
.amenu__acts a { color: var(--muted); text-decoration: none; transition: color .2s; }
.amenu__acts a:hover, .amenu__acts a:focus-visible { color: var(--fg); outline: none; }
.amenu__acts .amenu__give { color: #FF8FA3; }
.amenu__acts + .amenu__extra { border-top: 1px solid var(--line); }

/* Phone: it unrolls down from just under the bar, right-aligned under the
   disc — the same as the site's menu. The disc stays in the bar above it as the ×. */
@keyframes amenuDrop {
  from { transform: translateY(-10px); clip-path: inset(0 0 100% 0 round 34px); }
  to { transform: none; clip-path: inset(0 0 0 0 round 34px); }
}
@keyframes amenuLift { to { transform: translateY(-10px); clip-path: inset(0 0 100% 0 round 34px); } }
@media (max-width: 999.98px) {
  .amenu__panel {
    left: auto;
    right: 16px;
    width: min(300px, calc(100vw - 32px));
    max-height: calc(100dvh - 90px);
    padding: 8px 12px 10px;
    border-radius: 34px;
    animation: amenuDrop .5s cubic-bezier(.2, .9, .25, 1);
  }
  /* closing mirrors opening: it starts moving the moment you tap */
  .amenu__panel.is-closing { animation: amenuLift .22s cubic-bezier(.2, .9, .25, 1) both !important; }
  .amenu__word { font-size: 40px; }
}

/* Light theme (picked in Appearance, or the device's while on System): the
   menu and the desktop settings pop-up turn to light glass with dark ink */
:root[data-theme="light"] .amenu__panel,
:root[data-theme="light"] .asettings__pop {
  --fg: #130F0C; --bg: #FFFFFF;
  --line: color-mix(in srgb, #130F0C 12%, transparent);
  --well: color-mix(in srgb, #130F0C 7%, transparent);
  --muted: color-mix(in srgb, #130F0C 60%, transparent);
  color: #130F0C;
  background: color-mix(in srgb, #FFFFFF 92%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #130F0C 8%, transparent), inset 0 1px 0 0 #FFFFFF, 0 18px 40px -18px rgba(19,15,12,.3);
}
:root[data-theme="light"] .amenu__acts .amenu__give { color: #D6315A; }
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .amenu__panel,
  :root:not([data-theme="dark"]) .asettings__pop {
    --fg: #130F0C; --bg: #FFFFFF;
    --line: color-mix(in srgb, #130F0C 12%, transparent);
    --well: color-mix(in srgb, #130F0C 7%, transparent);
    --muted: color-mix(in srgb, #130F0C 60%, transparent);
    color: #130F0C;
    background: color-mix(in srgb, #FFFFFF 92%, transparent);
    box-shadow: inset 0 0 0 1px color-mix(in srgb, #130F0C 8%, transparent), inset 0 1px 0 0 #FFFFFF, 0 18px 40px -18px rgba(19,15,12,.3);
  }
  :root:not([data-theme="dark"]) .amenu__acts .amenu__give { color: #D6315A; }
}

/* ── Moving between the site, the Wiki and Studio ─────────────────────
   Same as the site's (styles.css). A cross-page view transition (Chrome, Edge, Safari 18.2+; elsewhere the
   page just changes). The brand carries over: the site's full wordmark
   shrinks and slides into the apps' w. mark (and grows back out of it on
   the way home), the wordmark fading as the mark comes in, with a small
   settle. The app's name slides in beside the mark, and the menu disc
   glides from its place in one bar to its place in the other. */
@view-transition { navigation: auto; }
::view-transition-group(whisper-brand) { animation-duration: .6s; animation-timing-function: cubic-bezier(.32, 1.12, .42, 1); }
::view-transition-old(whisper-brand),
::view-transition-new(whisper-brand) { height: 100%; object-fit: contain; }
/* old and new on the same clock: they add up to a whole mark the whole
   way, rather than both being half gone in the middle */
::view-transition-old(whisper-brand) { animation: vtBrandOut .3s ease both; }
::view-transition-new(whisper-brand) { animation: vtBrandIn .3s ease both; }
/* between the Wiki and Studio the name just crossfades where it stands —
   no stretch, no slide (arriving from the site, brand-morph.js brings it in) */
::view-transition-group(app-name) { animation-duration: .3s; }
::view-transition-old(app-name), ::view-transition-new(app-name) { width: auto; height: 100%; object-fit: none; object-position: left center; }
::view-transition-old(app-name) { animation: vtBrandOut .18s ease both; }
::view-transition-new(app-name) { animation: vtBrandIn .26s ease both; }
::view-transition-group(menu-disc) { animation-duration: .6s; animation-timing-function: cubic-bezier(.32, 1.12, .42, 1); }
::view-transition-old(menu-disc), ::view-transition-new(menu-disc) { height: 100%; object-fit: contain; }
::view-transition-old(menu-disc) { animation: vtBrandOut .3s ease both; }
::view-transition-new(menu-disc) { animation: vtBrandIn .3s ease both; }
@keyframes vtBrandOut { to { opacity: 0; } }
@keyframes vtBrandIn { from { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* brand morph (brand-morph.js): while the logo and the menu disc are being
   drawn in from the other side, the real ones wait hidden and sit out the
   view transition */
html.is-brand-morph .nav__brand .logo,
html.is-brand-morph .top__mark,
html.is-brand-morph .sbar__logo,
html.is-brand-morph .burger,
html.is-brand-morph .amenu__btn { visibility: hidden; view-transition-name: none; }
html.is-brand-morph .top__name,
html.is-brand-morph .sbar__name { view-transition-name: none; }
/* the drawing is its own layer of the page change, at full strength from
   the first frame: the page crossfades under it, it doesn't fade itself */
::view-transition-group(brand-morph),
::view-transition-new(brand-morph),
::view-transition-old(brand-morph) { animation: none; }

/* ── Collapsible sidebar (Wiki and Studio) ─────────────────────────────
   One width. Expanded is the rail as it was (184px). Collapsed is 68px:
   the same 10px of rail padding and 14px of item padding around a 20px
   icon, so the icons stay where they were and simply lose their labels.
   Phone layout never reads --rail. */
@property --rail {
  syntax: "<length>";
  inherits: true;
  initial-value: 184px;
}
:root { --rail: 184px; }
@media (min-width: 1000px) {
  :root[data-rail="collapsed"] { --rail: 68px; }
}
@media (min-width: 1000px) and (prefers-reduced-motion: no-preference) {
  html.rail-animate { transition: --rail .32s cubic-bezier(0.16, 1, 0.3, 1); }
}

.rail-toggle { display: none; }
@media (min-width: 1000px) {
  .rail-toggle {
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 64px;
    z-index: 1;
    display: flex;
    align-items: center;
    width: auto;
    padding: 10px 14px;
    border: 0;
    border-radius: 14px;
    background: transparent;
    color: var(--muted);
    cursor: pointer;
    transition: background-color .2s, color .2s;
  }
  /* Studio: Admin sits above Settings, so the control sits above Admin */
  .tabs .rail-toggle { bottom: 112px; }
  .rail-toggle:hover { color: var(--fg); background: color-mix(in srgb, var(--fg) 8%, transparent); }
  .rail-toggle svg {
    width: 20px;
    height: 20px;
    flex: none;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.25;
    stroke-linecap: round;
    stroke-linejoin: round;
  }
  .rail-toggle__chev { transform-box: fill-box; transform-origin: center; }
  html.rail-animate .rail-toggle__chev { transition: transform .32s cubic-bezier(0.16, 1, 0.3, 1); }
  :root[data-rail="collapsed"] .rail-toggle__chev { transform: scaleX(-1); }

  /* labels leave the row, but stay available to assistive tech */
  :root[data-rail="collapsed"] .tabbar .tab > span,
  :root[data-rail="collapsed"] .tabs .tab > span,
  :root[data-rail="collapsed"] .asettings__btn > span {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  html.rail-animate .rail-toggle__chev { transition: none; }
}
