/* Sky on the web (docs/PLAN-10.md): her sky is the whole browser window, at
   any size and any shape, and the interface is type set into it.

   The label's own values come from brand/tokens.json, through
   brand/tokens.css (the build copies it beside this file as tokens.css), so
   nothing here restates a token. What is here and not there is the phone's
   paper (Onboarding.swift's Paper.white and Paper.black), which the way in
   and the account are drawn on.

   Colour that belongs to her is never written in this file. It arrives as
   two custom properties main.js sets from her weather: --tint, her
   weather's first colour, and --shade, its darkest, taken down. They are
   registered, so when her weather turns they ramp with it. */

@font-face {
  font-family: 'Fraunces';
  src: url('/app/Fraunces.woff2') format('woff2'), url('/app/Fraunces.ttf') format('truetype');
  font-weight: 300 700;
  font-display: swap;
}

@property --tint { syntax: '<color>'; inherits: true; initial-value: #4C8FD8; }
@property --shade { syntax: '<color>'; inherits: true; initial-value: #183468; }

:root {
  /* the phone's paper, for the card, the price and the account */
  --paper: #FBFAF7;
  --paper-ink: #1B1A17;
  --paper-soft: #57534B;
  --paper-faint: #8A867D;
  --paper-rule: rgba(27, 26, 23, 0.12);
  --ink: var(--mmf-ink);
  --ink-dim: rgba(243, 236, 223, 0.78);
  --ink-faint: rgba(243, 236, 223, 0.56);
  --rule: var(--mmf-rule);
  --danger: var(--mmf-halation-ink);
  --face: var(--mmf-font);

  /* the type scale: the label's one face at sizes a phone cannot use */
  --t-hero: clamp(44px, 6.2vw, 96px);
  --t-display: clamp(34px, 4.4vw, 68px);
  --t-title: clamp(26px, 2.3vw, 34px);
  --t-body: 19px;
  --t-small: 14px;
  --t-label: var(--mmf-size-label);

  --gutter: clamp(20px, 5.4vw, 88px);
  --ramp: cubic-bezier(0.45, 0, 0.25, 1);
  --app-h: 100dvh;
  color-scheme: dark;
  transition: --tint var(--mmf-state-ramp) var(--ramp), --shade var(--mmf-state-ramp) var(--ramp);
}
@media (max-width: 719px) {
  :root { --t-body: 17px; --t-small: 13px; }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { background: var(--mmf-black); }
body {
  margin: 0; min-height: 100%; color: var(--ink); font-family: var(--face); font-optical-sizing: auto;
  font-size: var(--t-body); line-height: 1.5; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
/* Every screen but her page holds still: the window is the room. */
html.held, html.held body { height: 100%; overflow: hidden; overscroll-behavior: none; }
button, input, textarea { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }
a { color: inherit; }
p, h1, h2, h3 { margin: 0; font-weight: inherit; }
:focus { outline: none; }
:focus-visible { outline: 2px solid currentColor; outline-offset: 4px; border-radius: 6px; }
[hidden] { display: none !important; }
::selection { background: color-mix(in oklab, var(--tint) 70%, white); color: var(--paper-ink); }
.pre { white-space: pre-line; }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* --- the frame: her sky, the whole window ---------------------------------------------
   The canvas is larger than the window on every side by twice the blur, so
   that when it is blurred behind paper the blur has sky to draw from at the
   edges and not the black beyond them. engine/NOTICE.md: the engine sizes
   its own buffer from these CSS pixels, never from device pixels. */
/* iPhone Safari (iOS 26) paints the strip behind its status bar, and the one
   behind its toolbar, each in one flat colour: the colour at that edge of a
   fixed layer's CSS background (a gradient's ends count; a canvas's pixels
   do not), read once, at the first paint, and never again. Nothing fixed
   draws behind them. Her sky's layer used to be one flat blue, so the strips
   were two blue bars over a cloud. Now its background, hidden behind the
   portrait, runs from the colour her sky has along the top of the window to
   the colour it has along the bottom, which the page's head works out from
   her weather before anything is drawn (apps/web/build.mjs, --edge-top and
   --edge-bottom). Without WebGL this background is the window itself. */
#sky { position: fixed; inset: 0; z-index: 0; overflow: hidden;
  background-image: linear-gradient(to bottom, var(--edge-top, var(--tint)), var(--edge-top, var(--tint)) 12%, var(--edge-bottom, var(--tint)) 88%, var(--edge-bottom, var(--tint))); }
#portrait { position: absolute; inset: -80px; width: calc(100% + 160px); height: calc(100% + 160px); display: block;
  transition: filter 1.1s var(--ramp), opacity 1.1s var(--ramp); }
#sky.blurred #portrait { filter: blur(38px) saturate(1.05); }
#sky.slow #portrait { transition-duration: 2.6s; }
#sky.black #portrait { opacity: 0; }
#view { position: relative; z-index: 1; }
#over { position: fixed; inset: 0; z-index: 3; pointer-events: none; }
#over > * { pointer-events: auto; }

/* A screen that holds still fills the window; her page scrolls. Both fade. */
.screen { position: fixed; inset: 0; height: var(--app-h); opacity: 0; transition: opacity 0.55s var(--ramp); }
.flowing { position: relative; opacity: 0; transition: opacity 0.55s var(--ramp); overflow-x: clip; }
.screen.on, .flowing.on { opacity: 1; }

/* --- type -------------------------------------------------------------------------- */
.hero { font-size: var(--t-hero); font-weight: 400; line-height: 1.0; letter-spacing: -0.018em; text-wrap: balance; }
.display { font-size: var(--t-display); font-weight: 400; line-height: 1.06; letter-spacing: -0.012em; text-wrap: balance; }
.title { font-size: var(--t-title); font-weight: 450; line-height: 1.15; letter-spacing: -0.005em; text-wrap: balance; }
.body { font-size: var(--t-body); line-height: 1.5; }
.small { font-size: var(--t-small); line-height: 1.45; }
.label { font-size: var(--t-label); letter-spacing: 0.06em; line-height: 1.4; }
.dim { color: var(--ink-dim); }
.faint { color: var(--ink-faint); }
.figure { font-size: clamp(104px, 15vw, 232px); font-weight: 350; line-height: 0.9; letter-spacing: -0.035em; font-variant-numeric: lining-nums; }

/* White type on a sky that is itself half white (PLAN-10 §4). Not a box and
   not a drop shadow: a wide, soft fall of her own darkest colour under the
   words, so the line holds where the cloud is brightest and the sky still
   reads as sky. It is part of the words, so it fades with them. */
.veil { position: relative; isolation: isolate; }
.veil::before {
  content: ''; position: absolute; z-index: -1; pointer-events: none; inset: -38% -24% -42% -18%;
  background: radial-gradient(closest-side, color-mix(in oklab, var(--shade) 44%, transparent), color-mix(in oklab, var(--shade) 20%, transparent) 55%, transparent);
}
.lit { text-shadow: 0 0 1px color-mix(in oklab, var(--shade) 40%, transparent), 0 0 32px color-mix(in oklab, var(--shade) 32%, transparent); }
/* Small type has too little ink to carry a fall of shade on its own, so it
   gets a closer one. Labels only: body text never wears a shadow. */
.laurels, .room .bar, .lit-close { text-shadow: 0 0 2px color-mix(in oklab, var(--shade) 55%, transparent), 0 0 12px color-mix(in oklab, var(--shade) 50%, transparent), 0 0 28px color-mix(in oklab, var(--shade) 30%, transparent); }

/* --- controls: paper, ink, or her tint. Never the label's own colour ------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6em; min-height: 54px; padding: 0 30px;
  border-radius: 999px; background: var(--paper); color: var(--paper-ink); font-size: 18px; font-weight: 500; line-height: 1;
  white-space: nowrap; text-decoration: none; text-shadow: none;
  transition: background 0.25s var(--ramp), box-shadow 0.25s var(--ramp), opacity 0.25s var(--ramp), color 0.25s var(--ramp);
}
.btn:hover:not([disabled]) { background: #fff; box-shadow: 0 0 0 6px color-mix(in oklab, var(--paper) 22%, transparent); }
.btn:active:not([disabled]) { opacity: 0.86; }
.btn[disabled] { opacity: 0.4; cursor: default; }
.btn.ink { background: var(--paper-ink); color: var(--paper); }
.btn.ink:hover:not([disabled]) { background: #000; box-shadow: 0 0 0 6px rgba(27, 26, 23, 0.1); }
.btn.line { background: transparent; color: inherit; box-shadow: inset 0 0 0 1px currentColor; }
.btn.line:hover:not([disabled]) { background: color-mix(in oklab, currentColor 8%, transparent); box-shadow: inset 0 0 0 1px currentColor; }
.btn.wide { width: 100%; }
.btn.small { min-height: 42px; padding: 0 20px; font-size: 15px; }
.btn.glassy { background: color-mix(in oklab, var(--paper) 16%, transparent); color: var(--ink); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--paper) 46%, transparent);
  -webkit-backdrop-filter: blur(14px) saturate(1.3); backdrop-filter: blur(14px) saturate(1.3); }
.btn.glassy:hover:not([disabled]) { background: color-mix(in oklab, var(--paper) 30%, transparent); box-shadow: inset 0 0 0 1px var(--paper); }
.btn.dark { background: rgba(27, 26, 23, 0.84); color: var(--paper); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }
.btn.dark:hover:not([disabled]) { background: #000; box-shadow: 0 0 0 6px rgba(27, 26, 23, 0.14); }
.btn .key { font-size: 12px; letter-spacing: 0.06em; opacity: 0.55; font-weight: 400; }

.word { display: inline-flex; align-items: center; min-height: 44px; padding: 0 2px; font-size: var(--t-small); color: inherit;
  text-decoration: underline; text-decoration-color: transparent; text-underline-offset: 4px; transition: text-decoration-color 0.2s, opacity 0.2s; }
.word:hover { text-decoration-color: currentColor; }
.words { display: flex; flex-wrap: wrap; align-items: center; column-gap: 22px; }

/* --- the header: two words, at the top of her page. It scrolls away with it ------------------------------ */
.masthead { position: absolute; top: 0; left: 0; right: 0; z-index: 2; display: flex; justify-content: space-between; align-items: center;
  padding: max(14px, env(safe-area-inset-top)) var(--gutter) 0; pointer-events: none; }
.masthead > * { pointer-events: auto; }
.masthead .mark { font-size: 15px; letter-spacing: 0.04em; font-weight: 500; }
/* Her sky is often brightest at the top edge, so the two words sit on a
   fall of her own shade, as the room's top edge does. */
.masthead::before { content: ''; position: absolute; z-index: -1; inset: 0 0 auto 0; height: calc(env(safe-area-inset-top) + 110px); pointer-events: none;
  background: linear-gradient(to bottom, color-mix(in oklab, var(--shade) 46%, transparent), color-mix(in oklab, var(--shade) 16%, transparent) 60%, transparent); }
.masthead > * { text-shadow: 0 0 10px color-mix(in oklab, var(--shade) 45%, transparent); }

/* --- her page (/sky, signed out): the home page ----------------------------------------
   docs/PLAN-10.md §9. Her sky is still the whole window; what is new is that
   two stretches of the page are paper laid over it, so there is somewhere
   for a thread, a picture and a paragraph to sit that is not a cloud. */
.page section { position: relative; padding: clamp(72px, 12vh, 136px) var(--gutter); }
.page .eyebrow { display: flex; align-items: center; gap: 9px; font-size: 13px; letter-spacing: 0.06em; line-height: 1.3; margin-bottom: 18px; }
.page .eyebrow i { width: 8px; height: 8px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.page .sheet .eyebrow i { background: var(--tint); }

/* The page comes up as it is read. page.js adds .in from the scroll, never
   from an observer or a frame, so a background tab is never left blank. */
.page [data-reveal] { opacity: 0; transform: translateY(22px); transition: opacity 0.9s var(--ramp), transform 1s var(--ramp); }
.page [data-reveal].in { opacity: 1; transform: none; }

/* 1. the first screen: what to tell her turns, and the glass turns with it */
.page .first { min-height: 100svh; display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 32px clamp(32px, 5vw, 80px);
  align-items: end; padding-top: 112px; padding-bottom: clamp(40px, 8vh, 88px); }
.page .first .hero { font-size: clamp(44px, 5.9vw, 92px); }
.page .first .hero > span { display: block; }
.page .first .turn { position: relative; height: 3em; }
.page .first .say { position: absolute; top: 0; left: 0; white-space: pre; opacity: 0; transform: translateY(0.28em); transition: opacity 0.7s var(--ramp), transform 0.9s var(--ramp); }
.page .first .say.on { opacity: 1; transform: none; }
.page .first .say.out { opacity: 0; transform: translateY(-0.28em); }
.page .first .sub { margin-top: clamp(18px, 3vh, 28px); max-width: 37ch; }
.page .act { display: flex; align-items: center; flex-wrap: wrap; gap: 16px 24px; margin-top: clamp(22px, 4vh, 36px); }
.page .act .laurels:empty { display: none; }

/* The glass holds a person texting her. The bubbles are beside the glass,
   not in it: a frosted parent is a backdrop root, and a bubble that hangs
   over its edge would have nothing to frost. */
.page .frame { position: relative; justify-self: end; align-self: center; width: min(100%, 470px, calc((100svh - 210px) * 0.8)); aspect-ratio: 4 / 5; }
.page .glass { position: absolute; inset: 0; padding: 12px; border-radius: 44px; background: color-mix(in oklab, var(--paper) 18%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--paper) 44%, transparent), 0 50px 90px -50px color-mix(in oklab, var(--shade) 85%, transparent);
  -webkit-backdrop-filter: blur(18px) saturate(1.2); backdrop-filter: blur(18px) saturate(1.2); }
.page .glass .photos { position: relative; width: 100%; height: 100%; border-radius: 33px; overflow: hidden; background: color-mix(in oklab, var(--shade) 60%, transparent); }
.page .glass img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; opacity: 0; transition: opacity 1.2s var(--ramp); }
.page .glass img.on { opacity: 1; }
.page .frame .bubble { position: absolute; animation: none; }
.page .frame .bubble.mine { right: -22px; bottom: 112px; max-width: 260px; opacity: 0; transform: translateY(8px); transition: opacity 0.4s var(--ramp), transform 0.5s var(--ramp); }
.page .frame .bubble.mine.on { opacity: 1; transform: none; }
.page .frame .bubble.hers { left: -18px; bottom: 44px; }

/* 2. the story, in one breath */
.page .manifesto { min-height: 88svh; display: grid; place-items: center; text-align: center; }
.page .manifesto .veil { display: flex; flex-direction: column; align-items: center; gap: clamp(22px, 4vh, 40px); }
.page .manifesto .display { max-width: 21ch; }

/* paper, laid over her */
.page .sheet { --inset: clamp(8px, 1.1vw, 18px); position: relative; margin: 0 var(--inset); border-radius: clamp(30px, 4vw, 60px); overflow: clip;
  background: var(--paper); color: var(--paper-ink); box-shadow: 0 50px 120px -70px rgba(0, 0, 0, 0.55); }
.page .sheet section { padding: clamp(64px, 10vh, 120px) calc(var(--gutter) - var(--inset)) clamp(48px, 8vh, 96px); scroll-margin-top: 0; }
.page .sheet .body, .page .sheet .small, .page .sheet .eyebrow { color: var(--paper-soft); }
.page .sheet .word { color: inherit; }
.page .head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 0.8fr); gap: 20px clamp(32px, 6vw, 120px); align-items: end; margin-bottom: clamp(40px, 7vh, 80px); }
.page .head .display { max-width: 15ch; }
.page .head .aside { max-width: 36ch; justify-self: end; }

/* a thread on the page: the bubbles land one after another when it is reached */
.page .thread { display: flex; flex-direction: column; gap: 10px; width: 100%; max-width: 460px; padding: 28px; border-radius: 32px; background: rgba(27, 26, 23, 0.04); }
.page .thread[data-reveal] { opacity: 1; transform: none; }
.page .thread .bubble, .page .thread .day { animation: none; opacity: 0; transform: translateY(10px); transition: opacity 0.6s var(--ramp), transform 0.7s var(--ramp); transition-delay: calc(var(--i) * 0.5s + 0.15s); }
.page .thread.in .bubble, .page .thread.in .day { opacity: 1; transform: none; }
.page .thread .bubble { -webkit-backdrop-filter: none; backdrop-filter: none; color: var(--paper-ink); max-width: 88%; }
.page .thread .bubble.hers { background: color-mix(in oklab, var(--tint) 22%, var(--paper)); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--tint) 36%, transparent); }
.page .thread .bubble.mine { background: rgba(27, 26, 23, 0.07); box-shadow: none; }
.page .thread .day { color: var(--paper-faint); padding: 0 0 6px; }

/* 3a. her own person */
.page .own { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 48px clamp(32px, 6vw, 120px); align-items: center; }
.page .takes .eyebrow { margin-bottom: 14px; }
.page .take { font-size: var(--t-title); line-height: 1.2; padding: 20px 0; border-top: 1px solid var(--paper-rule); text-wrap: balance; }

/* 3b. what she keeps: the things around the thread that brings one back */
.page .memory { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 460px) minmax(0, 1fr); gap: 24px clamp(20px, 3vw, 56px); align-items: center; }
.page .memory .thread { justify-self: center; }
.page .side { display: flex; flex-direction: column; gap: clamp(18px, 3vh, 34px); }
.page .side.r { align-items: flex-end; }
.page .chip { margin: 0; width: 150px; display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; animation: drift 7s ease-in-out infinite alternate; }
.page .chip img { width: 108px; height: 108px; border-radius: 50%; object-fit: cover; box-shadow: 0 16px 30px -16px rgba(27, 26, 23, 0.55); }
.page .chip figcaption { font-size: 14px; line-height: 1.3; color: var(--paper-soft); text-wrap: balance; }
.page .side.l .chip:nth-child(1) { margin-left: 4%; }
.page .side.l .chip:nth-child(2) { margin-left: 24%; animation-delay: -2.3s; }
.page .side.l .chip:nth-child(3) { margin-left: 8%; animation-delay: -4.6s; }
.page .side.r .chip:nth-child(1) { margin-right: 20%; animation-delay: -1.2s; }
.page .side.r .chip:nth-child(2) { margin-right: 0; animation-delay: -3.4s; }
.page .side.r .chip:nth-child(3) { margin-right: 24%; animation-delay: -5.5s; }
.page .kept { margin-top: clamp(36px, 6vh, 64px); text-align: center; }
.page .kept .word { display: inline; min-height: 0; text-decoration-color: currentColor; }

/* 3c. her weather: the reader turns the window */
.page .weather { min-height: 100svh; display: flex; flex-direction: column; justify-content: center; gap: clamp(28px, 5vh, 48px); }
.page .weather .display { max-width: 14ch; }
.page .weather .body { margin-top: 20px; max-width: 41ch; }
.weather-keys { display: flex; flex-wrap: wrap; gap: 10px; }
.weather-key { display: inline-flex; align-items: center; gap: 10px; min-height: 52px; padding: 0 22px 0 8px; border-radius: 999px; font-size: 17px; color: var(--ink);
  background: rgba(28, 25, 23, 0.3); box-shadow: inset 0 0 0 1px var(--rule); -webkit-backdrop-filter: blur(22px) saturate(1.4) brightness(0.7); backdrop-filter: blur(22px) saturate(1.4) brightness(0.7);
  transition: background 0.3s var(--ramp), color 0.3s var(--ramp), box-shadow 0.3s var(--ramp); }
.weather-key i { width: 36px; height: 36px; border-radius: 50%; box-shadow: inset 0 0 0 1.5px rgba(251, 250, 247, 0.55); }
.weather-key:hover { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 55%, transparent); }
.weather-key[aria-checked="true"] { background: var(--paper); color: var(--paper-ink); box-shadow: none; }

/* 4. the research, straight on her night sky: no band of dusk behind it
   (the founder, 2026-11-13: it read as a shadow). Her night still has a
   pale cloud in it, so each line carries its own fall of shade instead:
   the close one for the small type, the soft one for the big. */
.page .research { min-height: 100svh; display: flex; flex-direction: column; justify-content: center; }
.page .research .figure, .page .research .display, .page .research .school { text-shadow: 0 0 1px color-mix(in oklab, var(--shade) 40%, transparent), 0 0 32px color-mix(in oklab, var(--shade) 40%, transparent); }
.page .research .body, .page .research .label, .page .research .small { color: var(--ink-dim); text-shadow: 0 0 2px color-mix(in oklab, var(--shade) 60%, transparent), 0 0 12px color-mix(in oklab, var(--shade) 50%, transparent), 0 0 28px color-mix(in oklab, var(--shade) 30%, transparent); }
.page .research .grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 56px clamp(32px, 6vw, 112px); align-items: start; }
.page .research .figure { font-size: clamp(88px, 11.5vw, 176px); }
.page .research .display { margin-top: 14px; max-width: 14ch; font-size: clamp(30px, 3.4vw, 52px); }
.page .research .body { margin-top: 14px; }
.page .research .label { margin-top: 16px; }
.page .research .backed { margin-top: clamp(28px, 5vh, 44px); padding-top: 4px; border-top: 1px solid var(--rule); }
.page .research .school { font-size: var(--t-title); line-height: 1.15; margin: 6px 0 10px; }

/* 5. everything else: three cards, and three rooms */
.page .cards { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.page .card-else { border-radius: 30px; background: rgba(27, 26, 23, 0.045); padding: 10px 10px 28px; display: flex; flex-direction: column; }
.page .card-else:nth-child(2) { transition-delay: 0.12s; }
.page .card-else:nth-child(3) { transition-delay: 0.24s; }
.page .card-else .pic { border-radius: 22px; overflow: hidden; aspect-ratio: 4 / 3; background: rgba(27, 26, 23, 0.08); }
.page .card-else img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 1.4s var(--ramp); }
.page .card-else:hover img { transform: scale(1.04); }
.page .card-else .title { margin: 22px 16px 8px; }
.page .card-else .body { margin: 0 16px; font-size: 17px; }
.page .sheet .rooms { padding-top: 0; }
.page .rooms .aside { display: flex; flex-direction: column; align-items: flex-end; }
.page .places { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 16px; }
.page .place { margin: 0; }
.page .place .shot { position: relative; aspect-ratio: 4 / 5; border-radius: 26px; overflow: hidden; background: rgba(27, 26, 23, 0.08); }
.page .place img { width: 100%; height: 100%; object-fit: cover; display: block; }
.page .place .bubble { position: absolute; right: 12px; bottom: 12px; max-width: calc(100% - 24px); animation: none; font-size: 16px; padding: 10px 14px; }
.page .place .jab { margin-top: 16px; font-size: 20px; font-weight: 500; line-height: 1.2; }
.page .place .sub { margin-top: 4px; font-size: 16px; color: var(--paper-soft); }

/* 6. one last line */
.page .last { min-height: 84svh; display: grid; place-items: center; text-align: center; }
.page .last .veil { display: flex; flex-direction: column; align-items: center; gap: clamp(28px, 5vh, 44px); }
.page .last .hero { max-width: 11ch; }
.page footer { padding: 64px var(--gutter) max(36px, env(safe-area-inset-bottom)); display: flex; flex-direction: column; gap: 24px; }
.page footer .care { max-width: 62ch; }
.page footer .mark { font-size: 15px; letter-spacing: 0.04em; font-weight: 500; margin-right: auto; }

/* what follows the reader down: one button, and where they are in her */
.page .afloat { position: fixed; top: max(12px, env(safe-area-inset-top)); right: var(--gutter); z-index: 4; opacity: 0; transform: translateY(-10px); pointer-events: none;
  transition: opacity 0.35s var(--ramp), transform 0.45s var(--ramp); }
.page .afloat.on { opacity: 1; transform: none; pointer-events: auto; }
.page .dock { position: fixed; left: 50%; bottom: max(18px, env(safe-area-inset-bottom)); z-index: 4; transform: translate(-50%, 14px); display: flex; gap: 2px; padding: 5px;
  border-radius: 999px; background: rgba(27, 26, 23, 0.82); white-space: nowrap; opacity: 0; pointer-events: none;
  box-shadow: 0 18px 50px -20px rgba(0, 0, 0, 0.5), inset 0 0 0 1px rgba(251, 250, 247, 0.1); -webkit-backdrop-filter: blur(18px) saturate(1.3); backdrop-filter: blur(18px) saturate(1.3);
  transition: opacity 0.35s var(--ramp), transform 0.45s var(--ramp); }
.page .dock.on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.page .dock button { min-height: 40px; padding: 0 16px; border-radius: 999px; font-size: 14px; color: rgba(251, 250, 247, 0.72); transition: background 0.3s var(--ramp), color 0.3s var(--ramp); }
.page .dock button:hover { color: var(--paper); }
.page .dock button[aria-current="true"] { background: var(--paper); color: var(--paper-ink); }
.page .dock button:focus-visible { outline-offset: -3px; }

/* the laurels: the label's live numbers, never typed by hand */
.laurels { display: flex; gap: 26px; align-items: center; min-height: 52px; }
.laurel { display: flex; align-items: center; gap: 7px; }
.laurel svg { width: 16px; height: 36px; opacity: 0.88; }
.laurel svg.flip { transform: scaleX(-1); }
.laurel .n { font-size: 20px; font-weight: 500; line-height: 1.1; }
.laurel .w, .laurel .when { font-size: 13px; line-height: 1.25; }
.laurel .when { opacity: 0.85; }

/* a thread, drawn as the room draws it: frosted so the weather reads through */
.sample { display: flex; flex-direction: column; gap: 10px; max-width: 420px; width: 100%; justify-self: end; }

/* --- plan cards: paper, annual chosen ------------------------------------------------ */
.plans { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.plan {
  position: relative; display: flex; flex-direction: column; align-items: flex-start; gap: 6px; min-height: 148px; padding: 22px 22px 20px;
  border-radius: 22px; background: var(--paper); color: var(--paper-ink); text-align: left; text-shadow: none;
  box-shadow: inset 0 0 0 1px var(--paper-rule); transition: box-shadow 0.25s var(--ramp), transform 0.25s var(--ramp);
}
.plan:hover { box-shadow: inset 0 0 0 1px rgba(27, 26, 23, 0.4); }
.plan[aria-checked="true"] { box-shadow: inset 0 0 0 2px var(--paper-ink); }
.plan .which { font-size: 15px; color: var(--paper-soft); display: flex; align-items: center; gap: 8px; }
.plan .which i { width: 9px; height: 9px; border-radius: 50%; box-shadow: inset 0 0 0 1px var(--paper-faint); transition: background 0.25s, box-shadow 0.25s; }
.plan[aria-checked="true"] .which i { background: var(--tint); box-shadow: none; }
.plan .stack-l { display: flex; flex-direction: column; gap: 4px; margin-top: auto; }
.plan .price { font-size: clamp(26px, 2.4vw, 38px); line-height: 1.05; letter-spacing: -0.01em; }
.plan .per { font-size: 14px; color: var(--paper-soft); }
.on-sky .plan { background: color-mix(in oklab, var(--paper) 94%, transparent); }

/* --- the paper card, over her blurred sky ---------------------------------------------- */
.centred { display: grid; place-items: center; padding: max(20px, env(safe-area-inset-top)) 20px max(20px, env(safe-area-inset-bottom)); overflow-y: auto; }
.card {
  width: min(100%, 420px); background: var(--paper); color: var(--paper-ink); border-radius: 28px; padding: 34px 32px 26px;
  display: flex; flex-direction: column; gap: 16px; box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.35);
}
.card.wide { width: min(100%, 760px); padding: 40px; }
.card .title { color: var(--paper-ink); }
.card .body, .card .small { color: var(--paper-soft); }
.card .body.ink { color: var(--paper-ink); }
.card .word { color: var(--paper-soft); }
.card .top { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.card .top .word { margin: -12px -2px 0 0; }
.card .or { display: flex; align-items: center; gap: 14px; color: var(--paper-faint); font-size: 13px; }
.card .or::before, .card .or::after { content: ''; flex: 1; height: 1px; background: var(--paper-rule); }
.card .said { color: var(--danger); font-size: 15px; }
.card .said.calm { color: var(--paper-soft); }

.tick { display: flex; align-items: center; gap: 12px; min-height: 44px; cursor: pointer; font-size: 16px; color: var(--paper-ink); user-select: none; }
.tick input { appearance: none; width: 22px; height: 22px; margin: 0; flex: 0 0 auto; border-radius: 7px; box-shadow: inset 0 0 0 1.5px var(--paper-soft); cursor: pointer; display: grid; place-items: center; transition: background 0.2s, box-shadow 0.2s; }
.tick input::after { content: ''; width: 10px; height: 6px; border-left: 2px solid var(--paper); border-bottom: 2px solid var(--paper); transform: translateY(-1px) rotate(-45deg); opacity: 0; transition: opacity 0.2s; }
.tick input:checked { background: var(--paper-ink); box-shadow: none; }
.tick input:checked::after { opacity: 1; }
.tick input:focus-visible { outline: 2px solid var(--paper-ink); outline-offset: 3px; }
.tick.want input { box-shadow: inset 0 0 0 2px var(--danger); }

.input { width: 100%; min-height: 54px; padding: 0 20px; border-radius: 16px; border: 0; background: rgba(27, 26, 23, 0.05);
  box-shadow: inset 0 0 0 1px var(--paper-rule); color: var(--paper-ink); font-size: 17px; transition: box-shadow 0.2s, background 0.2s; }
.input::placeholder { color: var(--paper-faint); }
.input:hover { box-shadow: inset 0 0 0 1px rgba(27, 26, 23, 0.3); }
.input:focus { background: #fff; box-shadow: inset 0 0 0 1.5px var(--paper-ink); }
.input.code { font-size: 30px; letter-spacing: 0.42em; text-align: center; padding: 0 0 0 0.42em; font-variant-numeric: tabular-nums lining-nums; min-height: 66px; }
.stack { display: flex; flex-direction: column; gap: 10px; }
.card .btn.line { color: var(--paper-ink); box-shadow: inset 0 0 0 1px rgba(27, 26, 23, 0.28); }
.card .btn.line:hover:not([disabled]) { background: rgba(27, 26, 23, 0.04); box-shadow: inset 0 0 0 1px var(--paper-ink); }

/* --- the way in: a focused flow that fills the window --------------------------------- */
.hairline { position: fixed; top: 0; left: 0; right: 0; height: 2px; z-index: 2; background: color-mix(in oklab, var(--ink) 14%, transparent); }
.hairline b { display: block; height: 100%; width: 0; background: var(--ink); transition: width 0.7s var(--ramp); }
.flow-top { position: fixed; top: 0; left: 0; right: 0; z-index: 2; display: flex; justify-content: space-between; align-items: center; padding: max(14px, env(safe-area-inset-top)) var(--gutter) 0; }
.ask-screen { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 32px clamp(40px, 7vw, 140px); align-items: center;
  padding: 96px var(--gutter) 64px; }
.ask-screen .q .display { max-width: 14ch; }
.ask-screen .q .small { margin-top: 18px; }
.ask-screen .q .go { margin-top: 40px; display: flex; align-items: center; gap: 18px; }
.ask-screen.solo { grid-template-columns: minmax(0, 1fr); align-content: end; padding-bottom: clamp(56px, 14vh, 140px); }
.choices { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: 1fr; gap: 8px; max-height: calc(var(--app-h) - 170px); overflow-y: auto; padding: 4px; }
.choices.two { grid-template-columns: 1fr 1fr; }
.choice {
  width: 100%; display: flex; align-items: center; gap: 16px; min-height: 54px; padding: 0 20px; border-radius: 16px; text-align: left;
  font-size: var(--t-body); color: var(--ink); background: color-mix(in oklab, var(--ink) 6%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 18%, transparent);
  transition: background 0.2s var(--ramp), box-shadow 0.2s var(--ramp);
}
.choice:hover { background: color-mix(in oklab, var(--ink) 11%, transparent); box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 40%, transparent); }
.choice .n { width: 1.2em; flex: 0 0 auto; font-size: 13px; letter-spacing: 0.04em; color: var(--ink-faint); font-variant-numeric: tabular-nums; }
.choice[aria-checked="true"] { background: color-mix(in oklab, var(--ink) 20%, transparent); box-shadow: inset 0 0 0 1.5px var(--ink); }
.choice[aria-checked="true"] .n { color: var(--ink); }
.choice:focus-visible { outline-offset: 2px; }
.name-field { width: 100%; max-width: 14ch; margin-top: 30px; background: none; border: 0; border-bottom: 1px solid color-mix(in oklab, var(--ink) 40%, transparent);
  font-size: var(--t-display); line-height: 1.2; padding: 0 0 8px; color: var(--ink); caret-color: var(--ink); border-radius: 0; transition: border-color 0.3s; }
.name-field::placeholder { color: color-mix(in oklab, var(--ink) 34%, transparent); }
.name-field:focus { border-bottom-color: var(--ink); outline: none; }
.hint { font-size: 12px; letter-spacing: 0.06em; color: var(--ink-faint); }
@media (pointer: coarse) { .hint { display: none; } }

/* the telling: their own introduction, typed for them over the stills */
.stills { position: fixed; inset: 0; background: #000 center / cover no-repeat; opacity: 0; transition: opacity 1s ease-in; }
.stills.on { opacity: 1; }
.stills::after { content: ''; position: absolute; inset: 0; background: linear-gradient(to top, rgba(0, 0, 0, 0.62), rgba(0, 0, 0, 0.3) 60%, rgba(0, 0, 0, 0.36)); }
.telling { display: flex; flex-direction: column; justify-content: flex-end; padding: 0 var(--gutter) clamp(56px, 14vh, 140px); }
.telling .hero { min-height: 1.05em; position: relative; }

/* introduced: four orbs in a row around their name */
.introduced { display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; padding: 80px var(--gutter) 56px; gap: clamp(40px, 7vh, 72px); }
.orbs { display: flex; align-items: center; justify-content: center; gap: clamp(18px, 3vw, 44px); }
.orbs .name { font-size: var(--t-display); font-weight: 400; padding: 0 clamp(8px, 2vw, 32px); max-width: 7em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.orb { display: flex; flex-direction: column; align-items: center; gap: 12px; opacity: 0; transform: scale(0.6); transition: opacity 0.8s var(--ramp), transform 0.9s cubic-bezier(0.34, 1.15, 0.64, 1); }
.orb.in { opacity: 1; transform: none; }
.orb i { width: clamp(64px, 7vw, 104px); aspect-ratio: 1; border-radius: 50%; box-shadow: 0 10px 22px rgba(20, 36, 70, 0.22), inset 0 0 0 1.5px rgba(251, 250, 247, 0.55); animation: drift 7s ease-in-out infinite alternate; }
.orb span { font-size: 14px; }
@keyframes drift { from { translate: 0 -4px; } to { translate: 0 4px; } }
.introduced .words-in { display: flex; flex-direction: column; gap: 10px; align-items: center; }
.fade { opacity: 0; transition: opacity 0.7s var(--ramp); }
.fade.in { opacity: 1; }

.threshold-line { position: fixed; inset: 0; display: grid; place-items: center; text-align: center; padding: 0 var(--gutter); }
.threshold-line .hero { opacity: 0; transition: opacity 0.9s var(--ramp); }
.threshold-line .hero.on { opacity: 1; }

/* --- the room ------------------------------------------------------------------------ */
.room { color: var(--ink); }
/* The thread scrolls up under her name. A mask would fade it, but a masked
   scroller is a backdrop root and the bubbles' frost would see nothing
   through it; so the top edge gets a fall of her own shade instead, which
   is also what her name and the one word sit on. */
.room::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: calc(env(safe-area-inset-top) + 120px); z-index: 1; pointer-events: none;
  background: linear-gradient(to bottom, color-mix(in oklab, var(--shade) 62%, transparent), color-mix(in oklab, var(--shade) 28%, transparent) 55%, transparent); }
.room .bar { position: absolute; top: 0; left: 0; right: 0; z-index: 2; display: flex; justify-content: space-between; align-items: center;
  padding: max(10px, env(safe-area-inset-top)) var(--gutter) 0; pointer-events: none; }
.room .bar > * { pointer-events: auto; }
.room .her { font-size: 20px; font-weight: 500; letter-spacing: 0.005em; min-height: 44px; display: flex; align-items: center; }
.room .bar .word { font-size: 15px; }
.room .scroller { position: absolute; inset: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: color-mix(in oklab, var(--ink) 30%, transparent) transparent; }
.room .column { width: min(100% - 2 * 20px, 640px); margin: 0 auto; min-height: 100%; display: flex; flex-direction: column; gap: 10px; padding-top: calc(env(safe-area-inset-top) + 84px); }
.room .push { flex: 1 0 0; }
.room .end { flex: 0 0 auto; height: 120px; }
.day { align-self: center; font-size: 12px; letter-spacing: 0.06em; color: var(--ink-dim); padding: 14px 0 6px; }
.bubble {
  max-width: min(85%, 520px); padding: 12px 17px; font-size: var(--t-body); line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere;
  /* The frost darkens what it shows, so her weather reads through it and
     white type still holds when the weather behind is bright. */
  -webkit-backdrop-filter: blur(22px) saturate(1.4) brightness(0.66); backdrop-filter: blur(22px) saturate(1.4) brightness(0.66); animation: land 0.45s var(--ramp) both;
}
.bubble.hers { align-self: flex-start; border-radius: 22px 22px 22px 7px; color: var(--ink);
  background: color-mix(in oklab, color-mix(in oklab, var(--tint) 36%, transparent), rgba(28, 25, 23, 0.3));
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--tint) 46%, transparent); }
.bubble.mine { align-self: flex-end; border-radius: 22px 22px 7px 22px; color: rgba(243, 236, 223, 0.94);
  background: color-mix(in oklab, rgba(243, 236, 223, 0.06), rgba(28, 25, 23, 0.36)); box-shadow: inset 0 0 0 1px rgba(243, 236, 223, 0.1); }
.bubble.picture { padding: 0; overflow: hidden; width: 240px; height: 240px; }
.bubble.picture img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bubble.typing { display: flex; gap: 5px; padding: 17px 18px; }
.bubble.typing i { width: 6px; height: 6px; border-radius: 50%; background: var(--ink); opacity: 0.35; animation: dot 1.14s infinite; }
.bubble.typing i:nth-child(2) { animation-delay: 0.38s; }
.bubble.typing i:nth-child(3) { animation-delay: 0.76s; }
.sample .bubble { animation: none; }
@keyframes dot { 0%, 33% { opacity: 0.9; } 34%, 100% { opacity: 0.35; } }
@keyframes land { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

.composer { position: absolute; left: 50%; transform: translateX(-50%); bottom: max(18px, calc(env(safe-area-inset-bottom) + 10px)); width: min(100% - 2 * 16px, 640px); z-index: 2;
  display: flex; align-items: flex-end; gap: 12px; padding: 10px 10px 10px 22px; border-radius: 26px;
  background: rgba(28, 25, 23, 0.36); box-shadow: inset 0 0 0 1px var(--rule), 0 18px 50px -24px rgba(0, 0, 0, 0.4);
  -webkit-backdrop-filter: blur(24px) saturate(1.4) brightness(0.66); backdrop-filter: blur(24px) saturate(1.4) brightness(0.66); transition: box-shadow 0.25s var(--ramp); }
.composer:focus-within { box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--ink) 38%, transparent), 0 18px 50px -24px rgba(0, 0, 0, 0.4); }
.composer textarea { flex: 1; min-width: 0; resize: none; background: none; border: 0; outline: none; color: var(--ink); font-size: var(--t-body); line-height: 1.45; padding: 7px 0; max-height: 168px; }
.composer textarea::placeholder { color: rgba(243, 236, 223, 0.5); }
.composer .send { flex: 0 0 auto; min-height: 40px; padding: 0 18px; border-radius: 999px; font-size: 15px; background: rgba(243, 236, 223, 0.1); color: rgba(243, 236, 223, 0.45); transition: background 0.2s, color 0.2s; }
.composer .send.can { background: var(--ink); color: var(--paper-ink); }
.composer .send:focus-visible { outline-offset: 2px; }
.composer .resting { flex: 1; text-align: center; font-size: 13px; letter-spacing: 0.06em; color: var(--ink-dim); min-height: 40px; display: grid; place-items: center; padding-right: 12px; }
.room .note { position: absolute; left: 0; right: 0; bottom: max(92px, calc(env(safe-area-inset-bottom) + 84px)); z-index: 2; text-align: center; font-size: 13px; letter-spacing: 0.06em; color: var(--ink-dim);
  opacity: 0; transition: opacity 0.4s var(--ramp); pointer-events: none; }
.room .note.on { opacity: 1; }

/* --- panels: from the right on a wide window, a sheet on a phone ---------------------- */
.panel-back { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.32); opacity: 0; transition: opacity 0.4s var(--ramp); }
.panel-back.on { opacity: 1; }
.panel {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(100%, 420px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--paper); color: var(--paper-ink); padding: max(28px, env(safe-area-inset-top)) 32px max(28px, env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: 14px; transform: translateX(104%); transition: transform 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
  box-shadow: -30px 0 80px -40px rgba(0, 0, 0, 0.45);
}
.panel.on { transform: none; }
.panel .title { color: var(--paper-ink); }
.panel .body, .panel .small { color: var(--paper-soft); }
.panel .word { color: var(--paper-soft); }
.panel .head { display: flex; justify-content: space-between; align-items: center; gap: 16px; }
.panel .who { padding: 14px 0 6px; border-bottom: 1px solid var(--paper-rule); }
.panel .who .small { margin-top: 2px; }
.setting { display: flex; justify-content: space-between; align-items: baseline; gap: 16px; width: 100%; min-height: 52px; padding: 12px 0;
  border-bottom: 1px solid var(--paper-rule); text-align: left; color: var(--paper-ink); font-size: 17px; transition: color 0.2s; }
.setting > span:last-child { color: var(--paper-soft); font-size: 14px; text-align: right; }
.setting:hover > span:first-child { text-decoration: underline; text-underline-offset: 4px; text-decoration-thickness: 1px; }
.setting.danger > span:first-child { color: var(--danger); }
.archive { display: flex; flex-direction: column; gap: 10px; }
.archive p { white-space: pre-line; font-size: 16px; }
.archive .me { color: var(--paper-soft); }
.archive h3 { font-size: 12px; letter-spacing: 0.06em; color: var(--paper-faint); margin: 12px 0 0; }
.where p + p { margin-top: 2px; }
.where .who-name { color: var(--paper-ink); font-size: 16px; }

/* --- the phone layout: under 720 it feels like what is live, not worse --------------- */
@media (max-width: 719px) {
  .page section { padding-top: 72px; padding-bottom: 64px; }
  .page .first { grid-template-columns: 1fr; align-items: start; min-height: 0; gap: 40px; padding-top: 104px; }
  .page .first .hero { font-size: clamp(44px, 13vw, 60px); }
  .page .act { flex-direction: column; align-items: stretch; gap: 14px; }
  .page .act .btn { width: 100%; }
  .page .act .hint-line { text-align: center; }
  .page .act .laurels { justify-content: center; }
  .page .frame { justify-self: center; width: min(100% - 12px, 380px); }
  .page .glass { border-radius: 36px; padding: 10px; }
  .page .glass .photos { border-radius: 27px; }
  .page .frame .bubble.mine { right: -6px; }
  .page .frame .bubble.hers { left: -6px; }
  .page .manifesto { min-height: 0; }
  .page .sheet section { padding-top: 56px; padding-bottom: 48px; }
  .page .head { grid-template-columns: 1fr; margin-bottom: 32px; }
  .page .head .aside { justify-self: start; align-items: flex-start; }
  .page .own, .page .memory, .page .research .grid, .page .cards { grid-template-columns: 1fr; }
  .page .thread { padding: 18px; border-radius: 26px; max-width: none; }
  .page .side, .page .side.r { flex-direction: row; justify-content: space-between; align-items: flex-start; gap: 8px; }
  .page .side .chip { width: 31%; margin: 0 !important; }
  .page .chip img { width: 84px; height: 84px; }
  .page .chip figcaption { font-size: 12.5px; }
  .page .weather, .page .research, .page .last { min-height: 0; }
  .page .last { padding-top: 96px; padding-bottom: 96px; }
  .page .places { grid-template-columns: 1fr; gap: 28px; }
  .page .dock button { padding: 0 12px; font-size: 13px; }
  .page .afloat { right: 14px; }
  .sample { justify-self: stretch; max-width: none; }
  .plans { grid-template-columns: 1fr; }
  .plan { min-height: 0; flex-direction: row; align-items: center; justify-content: space-between; padding: 18px 20px; }
  .plan .price { margin-top: 0; font-size: 24px; text-align: right; }
  .plan .stack-l { margin-top: 0; align-items: flex-end; }
  .centred { align-items: end; padding: 12px 12px max(12px, env(safe-area-inset-bottom)); }
  .card, .card.wide { padding: 28px 24px 22px; border-radius: 26px; }
  .ask-screen, .ask-screen.solo { grid-template-columns: 1fr; align-content: end; padding: 72px var(--gutter) max(28px, env(safe-area-inset-bottom)); gap: 26px; }
  .ask-screen .q .go { display: none; }
  .ask-screen .mobile-go { display: block; }
  .choices { max-height: none; overflow: visible; display: flex; flex-wrap: wrap; gap: 9px; padding: 0; }
  .choices.two { display: flex; }
  .choice { width: auto; min-height: 46px; padding: 0 16px; border-radius: 18px; font-size: 17px; }
  .choice .n { display: none; }
  .orbs { display: grid; grid-template-columns: 1fr auto 1fr; grid-template-areas: '. a .' 'b n c' '. d .'; gap: 10px; }
  .orbs > :nth-child(1) { grid-area: a; } .orbs > :nth-child(2) { grid-area: b; }
  .orbs > :nth-child(4) { grid-area: c; } .orbs > :nth-child(5) { grid-area: d; }
  .orbs .name { grid-area: n; max-width: 5.5em; }
  .room .column { width: calc(100% - 2 * 16px); padding-top: calc(env(safe-area-inset-top) + 64px); }
  .room .bar { padding-left: 18px; padding-right: 18px; }
  .bubble { max-width: calc(100% - 44px); padding: 11px 15px; }
  .composer { width: calc(100% - 2 * 14px); bottom: max(12px, calc(env(safe-area-inset-bottom) + 6px)); padding-left: 18px; }
  .room .note { bottom: max(80px, calc(env(safe-area-inset-bottom) + 76px)); }
  .panel { top: auto; left: 0; width: 100%; max-height: 92%; border-radius: 28px 28px 0 0; padding: 28px 24px max(28px, env(safe-area-inset-bottom)); transform: translateY(104%); }
  .panel.on { transform: none; }
}
.mobile-go { display: none; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important; transition-duration: 0.001s !important; }
  :root { transition: none; }
}
