/* The Floor: Jilani Place member app.
 *
 * MOTION LIVES NEXT DOOR. Every curve, duration and press scale in this
 * file is a token from /booking/shared/motion.css, which loads first.
 * Do not type a cubic-bezier or a duration here: pick the token whose
 * job matches the moment, and if none fits, the moment is probably
 * wrong. The one exception is the splash ident below, which is a brand
 * signature drawn once at boot and keeps its own timing.
 *
 * Warm cream, always. No dark mode, no prefers-color-scheme repaint:
 * the house identity is one light, warm surface, and an app that flips
 * to charcoal at night is a different brand wearing the same logo.
 * Tokens match the live booking site (public/booking/styles.css) so the
 * app and the site are recognisably one place.
 */

:root {
  --ink: #171716;
  --ink-2: #343431;
  --muted: #6e6d68;
  --ground: #f7f6f2;
  --paper: #ffffff;
  --line: #e4e2da;
  --line-soft: #efece4;
  --accent: #ffc838;
  --accent-ink: #171716;
  --cream: #f4f0e7;
  --night: #101816;
  --good: #2f7d5d;
  --warn: #a9601c;
  /* The one hue outside the house four, and it has exactly one job:
     affection on a post. It was a filled heart (2026-08-17) and became
     the raised cup on 2026-08-19 (design R3, Fahad retired the heart);
     the job did not change, only the glass. A grey mark reads as
     switched off and the gold means money in this app, so affection
     keeps its own warm brick. Do not spend this colour on anything
     else. */
  --ember: #b8402c;

  --r-lg: 20px;
  --r-md: 14px;
  --r-sm: 10px;
  --shadow: 0 1px 2px rgba(23,23,22,.05), 0 8px 24px rgba(23,23,22,.05);
  --shadow-lift: 0 2px 6px rgba(23,23,22,.07), 0 18px 44px rgba(23,23,22,.09);
  --tab-h: calc(58px + env(safe-area-inset-bottom, 0px));
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, serif;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0; padding: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-size-adjust: 100%;
  overscroll-behavior-y: none;
}

body { min-height: 100dvh; }

button { font: inherit; color: inherit; cursor: pointer; }
a { color: inherit; }

/* ------------------------------------------------------------ splash */
.boot { min-height: 100dvh; display: grid; place-items: center; }
.splash-mark { width: 46px; height: auto; animation: rise .7s ease both; }
.splash-mark path { fill: var(--ink); }
@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

/* -------------------------------------------------------- the ident */
/* The boot splash is the stage: a beat of cream, the mark drawn in a
   hairline of ink, the fill, one brass pass, the wordmark settling
   beneath. 1.5s, EVERY open, signed in or not; the ready screen fades
   in behind it and the mark glides into its seat. Reduced motion
   collapses it via the global rule below. */
.jmark { width: 56px; height: auto; }
/* The splash mark stands alone on a whole screen, so it gets the size
   the drawing needs. At 56px the three planes meet inside twenty pixels
   and the floor collapses into one dark blot: the bottom of the J reads
   as broken rather than as a room with a floor. At 96px every junction
   separates. The sign-in header keeps 56px, where the mark sits above a
   card and a bigger one would crowd it. */
.splash .jmark { width: 96px; }
.jmark .jm-fill { fill: var(--ink); }
.jmark .jm-stroke {
  fill: none; stroke: var(--ink); stroke-width: .5;
  stroke-dasharray: 1; stroke-dashoffset: 0; opacity: 0;
}
.jmark .jm-sweep { opacity: 0; }
.splash { text-align: center; }
.splash-word {
  font-family: var(--serif); font-size: 24px; letter-spacing: -.2px;
  margin-top: 18px;
}
.splash-sub {
  font-size: 11.5px; letter-spacing: .22em; text-transform: uppercase;
  color: var(--muted); margin-top: 7px;
}

/* 2.2s: a longer pen stroke earns the wait the data needs anyway. */
.jident.play .jm-stroke {
  animation: jm-draw 1.1s cubic-bezier(.65,0,.35,1) .15s both,
             jm-handoff .3s ease 1.3s both;
}
.jident.play .jm-fill { animation: jm-fillin .4s ease 1.1s both; }
.jident.play .jm-sweep {
  animation: jm-pass .5s cubic-bezier(.4,0,.2,1) 1.5s both;
}
.jident.play .splash-word {
  animation: jm-settle .5s cubic-bezier(.2,.7,.2,1) 1.35s both;
}
.jident.play .splash-sub {
  animation: jm-eyebrow .5s cubic-bezier(.2,.7,.2,1) 1.55s both;
}
@keyframes jm-eyebrow {
  from { opacity: 0; transform: translateY(6px); letter-spacing: .34em; }
}
@keyframes jm-draw {
  from { stroke-dashoffset: 1; opacity: 1; }
  to   { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes jm-handoff { from { opacity: 1; } to { opacity: 0; } }
@keyframes jm-fillin { from { opacity: 0; } }
@keyframes jm-pass {
  from { opacity: 1; transform: translateX(0); }
  to   { opacity: 1; transform: translateX(38px); }
}
@keyframes jm-settle {
  from { opacity: 0; transform: translateY(8px); letter-spacing: .12em; }
}
@keyframes jm-rise { from { opacity: 0; transform: translateY(8px); } }
@keyframes jm-seat {
  from { opacity: 0; visibility: hidden;
         transform: translateY(14px) scale(.985); }
}

/* After the ident, the sign-in screen only rises around the mark: the
   drawing already happened on the splash. */
.signin.enter .jm-word {
  animation: jm-settle .45s cubic-bezier(.2,.7,.2,1) .05s both;
}
.signin.enter .jm-line {
  animation: jm-rise .4s cubic-bezier(.2,.7,.2,1) .14s both;
}
.signin.enter .jm-card {
  animation: jm-seat .45s cubic-bezier(.22,1,.36,1) .22s both;
}

/* ------------------------------------------------------------- chrome */
.chrome {
  position: sticky; top: 0; z-index: 40;
  display: flex; align-items: center; gap: 12px;
  padding: max(10px, env(safe-area-inset-top, 0px)) 18px 10px;
  background: color-mix(in srgb, var(--cream) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--d-tap) var(--e-out);
}
.chrome.stuck { border-bottom-color: var(--line); }
.chrome-mark { width: 17px; height: auto; display: block; }
.chrome-mark path { fill: var(--ink); }
.chrome-title {
  font-family: var(--serif); font-size: 17px; letter-spacing: .2px;
  margin-right: auto;
}

/* The Circle chip lives in the chrome on every screen; a wallet is
   carried, not visited. It is also the only place a balance appears
   unprompted. */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line); background: var(--paper);
  border-radius: 999px; padding: 6px 12px 6px 10px;
  font-size: 14px; font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 2px rgba(23,23,22,.04);
  transition: transform var(--d-tap) var(--e-out),
              box-shadow var(--d-tap) var(--e-out);
}
.chip:active { transform: scale(var(--press-btn)); }
.chip.bump { animation: bump .5s var(--e-out); }
@keyframes bump {
  0% { transform: none; }
  35% { transform: scale(1.14); box-shadow: 0 4px 18px rgba(255,200,56,.5); }
  100% { transform: none; }
}
.jpe.jpe-sm { width: 17px; height: 17px; }

/* -------------------------------------------------------------- shell */
.wrap { padding: 4px 18px calc(var(--tab-h) + 26px); max-width: 620px;
        margin: 0 auto; }
.screen { animation: fade .22s ease both; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } }

h1.big {
  font-family: var(--serif); font-weight: 400;
  font-size: 30px; line-height: 1.15; margin: 12px 0 2px;
  letter-spacing: -.2px;
}
.sub { color: var(--muted); font-size: 14px; margin: 0 0 18px; }

.sect { margin: 26px 0 10px; display: flex; align-items: baseline; gap: 10px; }
.sect h2 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--muted); font-weight: 600; margin: 0;
}
.sect .more { margin-left: auto; font-size: 13px; color: var(--muted);
              background: none; border: 0; padding: 0; }

.card {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 16px 18px;
  box-shadow: var(--shadow); margin-bottom: 12px;
}
.card.flush { padding: 0; overflow: hidden; }
.card.quiet { background: transparent; box-shadow: none;
              border-style: dashed; }

/* The hero card: one card, four states, so a hot-desker, an office
   tenant and someone who booked one podcast session all get a correct
   first screen. */
.hero {
  background: linear-gradient(160deg, var(--night) 0%, #17231f 100%);
  color: #f2efe6; border: 0; border-radius: var(--r-lg);
  padding: 20px; box-shadow: var(--shadow-lift); margin-bottom: 14px;
}
.hero .kicker {
  font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: #b9c4bd; margin-bottom: 8px;
}
.hero h3 { font-family: var(--serif); font-weight: 400; font-size: 23px;
           margin: 0 0 4px; }
.hero .when { color: #cfd8d1; font-size: 14px; }
.hero .row { display: flex; gap: 8px; margin-top: 16px; flex-wrap: wrap; }
/* What the room already has, and the way to change it. One tappable row
   rather than a fifth button in a row that already wraps on a phone. */
.hero .hprep {
  display: flex; align-items: center; gap: 10px; width: 100%;
  margin-top: 12px; padding: 11px 12px 11px 14px;
  background: rgba(242, 239, 230, .07); border: 0;
  border-radius: var(--r-md); color: #cfd8d1;
  font: inherit; font-size: 13.5px; text-align: left;
  transition: background var(--d-tap) var(--e-out),
              transform var(--d-tap) var(--e-out);
}
.hero .hprep:active { transform: scale(var(--press-row)); background: rgba(242,239,230,.11); }
.hero .hprep > span { flex: 1; min-width: 0; }
.hero .hprep .jpi { width: 16px; height: 16px; flex: none; opacity: .55;
                    stroke: currentColor; stroke-width: 2;
                    stroke-linecap: round; stroke-linejoin: round; }
.hero .hprep::before {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 999px;
  border: 1.5px solid rgba(207, 216, 209, .45); background: transparent;
}
.hero .hprep.on { color: #f2efe6; }
.hero .hprep.on::before { background: var(--accent); border-color: var(--accent); }

.btn {
  border: 1px solid var(--ink); background: var(--ink); color: var(--cream);
  border-radius: 999px; padding: 11px 18px; font-size: 15px;
  font-weight: 500; transition: transform var(--d-tap) var(--e-out),
                                opacity var(--d-tap) var(--e-out);
  /* Thirteen of these are <a>, not <button>. Without these three lines an
     anchor keeps its underline and stays inline, so .wide does nothing:
     "Message the desk" on the Circle activity tab was an underlined pill
     hugging its own text. Seven call sites had patched it by hand with
     inline styles; the component should carry it. */
  display: inline-block; text-align: center; text-decoration: none;
}
.btn:active { transform: scale(var(--press-btn)); }
.btn.ghost { background: transparent; color: var(--ink); }
.btn.onDark { background: var(--cream); color: var(--ink); border-color: transparent; }
.btn.onDark.ghost { background: transparent; color: #f2efe6;
                    border-color: rgba(242,239,230,.32); }
.btn.gold { background: var(--accent); border-color: var(--accent);
            color: var(--accent-ink); }
.btn.wide { width: 100%; }
.btn[disabled] { opacity: .4; pointer-events: none; }
.btn.sm { padding: 8px 14px; font-size: 14px; }

/* --------------------------------------------------------- room state */
.rooms { display: grid; gap: 8px; }
.room {
  display: flex; align-items: center; gap: 12px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px;
}
.room .nm { font-size: 15px; }
.room .st { margin-left: auto; font-size: 13px; color: var(--muted); }
.room .st.free { color: var(--good); }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--line);
       flex: none; }
.dot.free { background: var(--good); }

/* ------------------------------------------------------------ meters */
.meter { height: 6px; border-radius: 999px; background: var(--line-soft);
         overflow: hidden; }
.meter > i { display: block; height: 100%; background: var(--ink);
             border-radius: 999px; transition: width var(--d-slow) var(--e-out); }
.meter.gold > i { background: var(--accent); }
.meterRow { display: flex; justify-content: space-between; font-size: 13px;
            margin-bottom: 7px; }
.meterRow b { font-weight: 600; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------- floor */
.person {
  display: flex; gap: 12px; align-items: flex-start;
  padding: 14px 0; border-bottom: 1px solid var(--line-soft);
}
.person:last-child { border-bottom: 0; }
.av {
  width: 42px; height: 42px; border-radius: 50%; flex: none;
  background: var(--cream); border: 1px solid var(--line);
  display: grid; place-items: center; font-family: var(--serif);
  font-size: 16px; color: var(--ink-2); overflow: hidden;
}
/* The mark that stands in for a person we have no name for. Sized as a
   share of its circle, so the same glyph serves the 26px comment avatar
   and the 96px monogram; every one of those containers centres its child
   already. Quieter than lettering on purpose: it is the absence of a
   name, and it should not compete with the people who have one. */
.avic { width: 52%; height: 52%; fill: none; stroke: currentColor;
        stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
        opacity: .5; }
.av img { width: 100%; height: 100%; object-fit: cover; }
.person .nm { font-size: 15px; font-weight: 500; }
.person .why { font-size: 13px; color: var(--muted); margin-top: 2px; }
.person .work { font-size: 12px; color: var(--muted); margin-top: 3px;
                opacity: .85; }
.tagrow { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.tag {
  font-size: 12px; border: 1px solid var(--line); border-radius: 999px;
  padding: 3px 9px; color: var(--ink-2); background: var(--ground);
}
.tag.on { background: var(--ink); color: var(--cream); border-color: var(--ink); }
.tag.match { background: #fff6dd; border-color: #f2dc9e; }

.intent {
  font-size: 12px; border-radius: 999px; padding: 3px 9px;
  background: var(--cream); border: 1px solid var(--line); color: var(--ink-2);
  white-space: nowrap;
}

/* the hand-raise control */
.raise { text-align: center; padding: 22px 18px; }
.raise h3 { font-family: var(--serif); font-weight: 400; font-size: 20px;
            margin: 0 0 6px; }
.raise p { color: var(--muted); font-size: 14px; margin: 0 0 16px;
           line-height: 1.45; }
.choices { display: flex; gap: 8px; justify-content: center;
           flex-wrap: wrap; margin-bottom: 14px; }
.choice {
  border: 1px solid var(--line); background: var(--paper);
  border-radius: 999px; padding: 9px 15px; font-size: 14px;
}
.choice.on { background: var(--ink); color: var(--cream); border-color: var(--ink); }

.live {
  display: inline-flex; align-items: center; gap: 7px; font-size: 13px;
  color: var(--good); background: #eaf4ef; border: 1px solid #cfe6da;
  border-radius: 999px; padding: 5px 12px;
}
.live i { width: 6px; height: 6px; border-radius: 50%; background: var(--good);
          animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 50% { opacity: .35; } }

/* ------------------------------------------------------------ circle */
.standing { text-align: center; padding: 26px 18px 20px; }
.bal {
  font-family: var(--serif); font-size: 52px; line-height: 1;
  font-variant-numeric: tabular-nums; letter-spacing: -1px;
}
.bal .u { font-size: 17px; color: var(--muted); margin-left: 8px;
          font-family: var(--sans); letter-spacing: 0; }
.bal.roll { animation: none; }
.worth { color: var(--muted); font-size: 13px; margin-top: 6px; }
.tierline { font-size: 14px; margin-top: 18px; }
.tierline b { font-weight: 600; }
.tierline .muted { color: var(--muted); font-size: 13px; }

.reward {
  display: flex; gap: 14px; align-items: center; padding: 14px 0;
  border-bottom: 1px solid var(--line-soft);
}
.reward:last-child { border-bottom: 0; }
.reward .body { flex: 1; min-width: 0; }
.reward .t { font-size: 15px; }
.reward .b { font-size: 13px; color: var(--muted); margin-top: 2px;
             line-height: 1.4; }
.reward .pts {
  font-variant-numeric: tabular-nums; font-size: 14px; white-space: nowrap;
  text-align: right;
}
.reward .pts .away { display: block; font-size: 12px; color: var(--muted);
                     margin-top: 2px; }
/* Locked rewards stay full colour with the distance shown. Greyscale and
   padlocks read as punishment; the distance is the point. */
.reward.locked { opacity: .78; }
.reward.saving { background: #fffaf0; border-radius: var(--r-md);
                 padding: 14px 12px; margin: 4px -12px; border-bottom: 0; }
.pin { font-size: 12px; color: var(--warn); }

.ledger { width: 100%; border-collapse: collapse; font-size: 14px; }
.ledger td { padding: 11px 0; border-bottom: 1px solid var(--line-soft);
             vertical-align: top; }
.ledger tr:last-child td { border-bottom: 0; }
.ledger .d { text-align: right; font-variant-numeric: tabular-nums;
             white-space: nowrap; }
.ledger .d.pos { color: var(--good); }
.ledger .run { display: block; font-size: 12px; color: var(--muted);
               margin-top: 2px; }
.ledger .note { color: var(--muted); font-size: 12px; margin-top: 2px; }
.bonusdot { display: inline-block; width: 6px; height: 6px; border-radius: 50%;
            background: var(--accent); margin-right: 6px; }

.code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 34px; letter-spacing: 3px; text-align: center;
  padding: 18px 0 6px;
}

/* --------------------------------------------------------------- tabs */
.tabs {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  /* One column per tab it actually holds: the member app has five,
     the signed-out Lobby four, and a fixed repeat(5) left the Lobby's
     four hugging the left with a phantom fifth column (2026-08-23). */
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  background: color-mix(in srgb, var(--cream) 92%, transparent);
  backdrop-filter: saturate(1.4) blur(16px);
  -webkit-backdrop-filter: saturate(1.4) blur(16px);
  border-top: 1px solid var(--line);
  padding-bottom: env(safe-area-inset-bottom, 0px);
}
.tab {
  background: none; border: 0; padding: 9px 0 7px;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  color: var(--muted); font-size: 10.5px; letter-spacing: .02em;
}
.tab svg { width: 21px; height: 21px; fill: none; stroke: currentColor;
           stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tab.on { color: var(--ink); }
.tab .badge {
  position: absolute; transform: translate(13px, -6px);
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
}

/* -------------------------------------------------------------- sheet */
.veil {
  position: fixed; inset: 0; z-index: 60; background: rgba(23,23,22,.34);
  backdrop-filter: blur(2px); opacity: 0; transition: opacity var(--d-enter) var(--e-out);
  display: flex; align-items: flex-end; justify-content: center;
}
.veil.in { opacity: 1; }
.sheet {
  background: var(--cream); width: 100%; max-width: 560px;
  border-radius: 22px 22px 0 0; padding: 8px 18px
    calc(20px + env(safe-area-inset-bottom, 0px));
  transform: translateY(102%); transition: transform var(--d-enter) var(--e-out);
  max-height: 90dvh; overflow-y: auto;
}
.veil.in .sheet { transform: none; }
.grab { width: 38px; height: 4px; border-radius: 999px; background: var(--line);
        margin: 6px auto 14px; }
.sheet h3 { font-family: var(--serif); font-weight: 400; font-size: 21px;
            margin: 0 0 6px; }
.sheet p { color: var(--muted); font-size: 14px; line-height: 1.5;
           margin: 0 0 16px; }
.sheet .btn { margin-top: 4px; }

.field { margin-bottom: 14px; }
.field label { display: block; font-size: 13px; color: var(--muted);
               margin-bottom: 6px; }
.field input, .field textarea, .field select {
  width: 100%; font: inherit; font-size: 16px; color: var(--ink);
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px;
}
.field textarea { min-height: 84px; resize: vertical; }
.count { font-size: 12px; color: var(--muted); text-align: right;
         margin-top: 4px; }

.toast {
  position: fixed; left: 50%; bottom: calc(var(--tab-h) + 16px);
  transform: translate(-50%, 12px); z-index: 70;
  /* Never a tap target, shown OR hidden: the pill lingers at opacity 0
     after its fade, exactly where sheet buttons and the tab bar live,
     and an invisible pill was eating those taps (found 2026-08-24
     verifying team seats: a confirm sheet's Remove would not press). */
  pointer-events: none;
  background: var(--ink); color: var(--cream); font-size: 14px;
  padding: 11px 18px; border-radius: 999px; opacity: 0;
  transition: opacity var(--d-tap) var(--e-out),
              transform var(--d-tap) var(--e-out);
  box-shadow: var(--shadow-lift); max-width: 88vw; text-align: center;
}
.toast.in { opacity: 1; transform: translate(-50%, 0); }

.empty { text-align: center; color: var(--muted); font-size: 14px;
         padding: 26px 10px; line-height: 1.55; }

.note-desk .who { font-size: 12px; color: var(--muted); margin-top: 8px; }
.answer { padding: 12px 0; border-bottom: 1px solid var(--line-soft); }
.answer:last-child { border-bottom: 0; }
/* A desk answer and a member answer are separate components on purpose,
   so they can never drift into looking like each other. */
.answer.desk { background: var(--ground); border-radius: var(--r-md);
               padding: 12px 14px; margin: 6px 0; border-bottom: 0; }
.answer .who { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.answer.desk .who { color: var(--warn); font-weight: 600; }

.inline-link { background: none; border: 0; padding: 0; font-size: 14px;
               color: var(--ink); text-decoration: underline;
               text-underline-offset: 3px; text-decoration-color: var(--line); }

.danger { color: #9a2f2f; }

/* --------------------------------------------------------- guest kit */
.guest { max-width: 520px; margin: 0 auto; padding: 30px 22px 60px; }
.guest .mark { width: 26px; margin-bottom: 22px; }
.guest .mark path { fill: var(--ink); }
.guest h1 { font-family: var(--serif); font-weight: 400; font-size: 27px;
            margin: 0 0 8px; line-height: 1.2; }
.guest .step { display: flex; gap: 14px; padding: 16px 0;
               border-bottom: 1px solid var(--line); }
.guest .step:last-of-type { border-bottom: 0; }
.guest .n { width: 25px; height: 25px; border-radius: 50%; flex: none;
            background: var(--ink); color: var(--cream); font-size: 13px;
            display: grid; place-items: center; }
.guest .step h4 { margin: 0 0 3px; font-size: 15px; font-weight: 600; }
.guest .step p { margin: 0; color: var(--muted); font-size: 14px;
                 line-height: 1.5; }

/* ------------------------------------------------------------ desktop
   One app, wider, never a separate desktop product. The tab bar becomes
   a left rail and the canvas gets room; nothing else changes. */
@media (min-width: 900px) {
  /* The grid goes on #app, not body: #app is body's only child, so a grid
     on body puts the entire app inside the 232px rail column. */
  #app {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    grid-template-areas: "rail head" "rail body";
    align-items: start;
  }
  .chrome { grid-area: head; }
  .wrap { grid-area: body; }
  .tabs {
    grid-area: rail;
    position: sticky; top: 0; bottom: auto; height: 100dvh;
    display: flex; flex-direction: column; align-items: stretch;
    justify-content: flex-start; gap: 2px;
    border-top: 0; border-right: 1px solid var(--line);
    padding: 26px 14px; background: transparent; backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .tab { flex-direction: row; justify-content: flex-start; gap: 12px;
         padding: 11px 14px; border-radius: 12px; font-size: 14.5px; }
  .tab.on { background: var(--paper); box-shadow: var(--shadow); }
  .tab .badge { position: static; transform: none; margin-left: auto; }
  .chrome { padding-left: 30px; padding-right: 30px; }
  .wrap { padding: 4px 30px 60px; max-width: 720px; }
  :root { --tab-h: 0px; }
  .veil { align-items: center; }
  .sheet { border-radius: 20px; max-width: 460px; margin: 0 20px;
           transform: translateY(14px) scale(.98); }
  .veil.in .sheet { transform: none; }
}

/* motion.css owns reduced motion and zeroes the tokens too. This stays
   as the floor under it: if the shared sheet ever fails to load, the app
   still holds still for someone who asked it to. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* --------------------------------------------- circle, the R4 display */
.standing .brag { color: var(--muted); font-size: 13px; margin-top: 3px;
                  text-align: center; }
.clockline { color: var(--muted); font-size: 12.5px; margin-top: 8px; }
.jpc-mhead { display: flex; justify-content: space-between;
             align-items: baseline; margin: 14px 2px 4px; }
.jpc-mhead:first-child { margin-top: 2px; }
.jpc-mhead > span:first-child { font-family: var(--serif);
  font-size: 12.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-2); }
.jpc-net { font-size: 13px; font-variant-numeric: tabular-nums;
           color: var(--muted); }
.jpc-net.pos { color: var(--good); }
.jpc-row { display: flex; gap: 12px; padding: 10px 2px;
           border-top: 1px solid var(--line-soft); align-items: flex-start; }
.jpc-tx { flex: 1; min-width: 0; }
.jpc-tx .t { font-size: 14.5px; }
.jpc-tx .n { font-size: 12.5px; color: var(--muted); margin-top: 2px;
             overflow-wrap: anywhere; }
.jpc-amt { text-align: right; font-variant-numeric: tabular-nums; }
.jpc-amt b { font-weight: 500; font-size: 14.5px; }
.jpc-amt .pos { color: var(--good); }
.jpc-amt .run { display: block; font-size: 11.5px; color: var(--muted);
                margin-top: 2px; }
.jpc-links { display: flex; gap: 18px; justify-content: center;
             margin: 18px 0 6px; }
.jpc-stmt h3, .jpc-how h3 { font-family: var(--serif); font-weight: 400;
                            font-size: 21px; margin: 0 0 12px; }
.jpc-line { display: flex; justify-content: space-between; padding: 8px 0;
            border-top: 1px solid var(--line-soft); font-size: 14.5px; }
.jpc-line b { font-weight: 500; font-variant-numeric: tabular-nums; }
.jpc-line.quiet { color: var(--muted); }
.jpc-months { display: grid; grid-template-columns: repeat(4, 1fr);
              gap: 8px; margin: 12px 0 4px; }
.jpc-cell { background: var(--line-soft); border-radius: var(--r-sm);
            padding: 8px; text-align: center; font-size: 12px; }
.jpc-cell b { display: block; font-variant-numeric: tabular-nums;
              margin-top: 2px; }
.jpc-foot { color: var(--muted); font-size: 12.5px; margin: 14px 0 0;
            text-align: center; }
.jpc-how p { font-size: 14.5px; line-height: 1.5; margin: 0 0 10px; }

/* -------------------------------------- circle, the Aeroplan pass (R4) */
.ccard {
  position: relative; overflow: hidden;
  background: linear-gradient(165deg, var(--night) 0%, #17231f 78%, #1d2b26 100%);
  color: #f2efe6; border-radius: 24px; padding: 20px 20px 18px;
  box-shadow: var(--shadow-lift); margin-bottom: 12px;
}
.ccard-wm { position: absolute; right: -18px; top: -10px; width: 130px;
            height: auto; opacity: .07; }
.ccard-wm path { fill: #f2efe6; }
.ccard-top { display: flex; justify-content: space-between;
             align-items: baseline; }
.ccard-brand { font-size: 11px; letter-spacing: .16em;
               text-transform: uppercase; color: #b9c4bd; }
.ccard-tier { font-size: 12.5px; color: var(--accent); font-weight: 600; }
.ccard-bal { font-family: var(--serif); font-size: 56px; line-height: 1.05;
             letter-spacing: -1px; margin: 12px 0 2px; }
.ccard-bal small { font-size: 16px; letter-spacing: 0; color: #cfd8d1;
                   font-family: var(--sans); margin-left: 8px; }
.ccard-pills { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
.cpill { border-radius: 999px; padding: 6px 12px; font-size: 12.5px;
         background: rgba(242,239,230,.1); color: #e9e5d8;
         border: 1px solid rgba(242,239,230,.14); }
.cpill.gold { background: var(--accent); color: var(--ink);
              border-color: var(--accent); font-weight: 600; }
.ccard-name { margin-top: 14px; font-size: 12px; letter-spacing: .08em;
              text-transform: uppercase; color: #93a29b; }

/* the status journey (R10: six stations, a scrollable road) */
.msts { display: grid; grid-template-columns: repeat(6, minmax(108px, 1fr));
        gap: 8px; margin: 12px 0 0; position: relative;
        overflow-x: auto; -webkit-overflow-scrolling: touch;
        scrollbar-width: none; padding-bottom: 2px; }
.msts::-webkit-scrollbar { display: none; }
.msts::before { content: ""; position: absolute; left: 8%; right: 8%;
                top: 36px; height: 2px; background: var(--line); }
.mst { position: relative; background: var(--paper);
       border: 1px solid var(--line); border-radius: var(--r-md);
       padding: 14px 10px 12px; text-align: center; }
/* the tier roundel: the number is the badge, set in the serif */
.tbadge { width: 44px; height: 44px; border-radius: 50%;
          margin: 0 auto 9px; display: grid; place-items: center;
          position: relative; z-index: 1; background: var(--paper);
          border: 1.5px solid var(--line); color: var(--muted); }
.tbadge i { font-style: normal; font-family: var(--serif);
            font-size: 13.5px; letter-spacing: .01em; line-height: 1;
            font-variant-numeric: tabular-nums; }
.tbadge svg { width: 24px; height: 24px; display: block; }
.tbadge.hit { background: var(--night); border-color: var(--night);
              color: var(--accent); }
.tbadge.cur { border-color: var(--accent); color: var(--ink);
              box-shadow: 0 0 0 3px rgba(255,200,56,.18); }
.mst.cur { border-color: var(--accent);
           box-shadow: 0 0 0 3px rgba(255,200,56,.18); }
.mst-l { font-size: 13px; font-weight: 600; }
.mst-a { font-size: 11.5px; color: var(--muted); margin-top: 2px;
         font-variant-numeric: tabular-nums; }
.mst-p { font-size: 10.5px; color: var(--warn); margin-top: 3px; }
.mst-bar { height: 4px; border-radius: 999px; background: var(--line-soft);
           margin-top: 8px; overflow: hidden; }
.mst-bar i { display: block; height: 100%; background: var(--accent); }
.mst-togo { font-size: 10.5px; color: var(--muted); margin-top: 5px;
            font-variant-numeric: tabular-nums; }

/* stat tiles */
.cstats { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px;
          margin: 12px 0 0; }
.cstat { background: var(--paper); border: 1px solid var(--line);
         border-radius: var(--r-md); padding: 11px 12px; }
.cstat .n { font-family: var(--serif); font-size: 19px;
            font-variant-numeric: tabular-nums; }
.cstat .l { font-size: 10.5px; color: var(--muted);
            text-transform: uppercase; letter-spacing: .08em;
            margin-top: 3px; }

/* education pair */
.edus { display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
        margin: 24px 0 0; }
.edu { display: flex; gap: 10px; align-items: center;
       background: var(--paper); border: 1px solid var(--line);
       border-radius: var(--r-md); padding: 12px; }
.edu .coin { width: 44px; height: 44px; border-radius: 50%; flex: none;
             background: var(--accent); display: flex;
             flex-direction: column; align-items: center;
             justify-content: center; line-height: 1;
             font-family: var(--serif); color: var(--ink);
             font-variant-numeric: tabular-nums;
             box-shadow: inset 0 0 0 2px rgba(23,23,22,.14); }
.edu .coin b { font-weight: 400; font-size: 15px;
               letter-spacing: -.2px; }
.edu .coin small { font-size: 7.5px; font-family: var(--sans);
                   font-weight: 600; letter-spacing: .05em;
                   text-transform: uppercase; margin-top: 2px;
                   color: rgba(23,23,22,.72); }
.edu b { display: block; font-size: 12.5px; }
.edu span { display: block; font-size: 11.5px; color: var(--muted);
            margin-top: 2px; line-height: 1.35; }

/* reward tile rails */
.rtiles { display: flex; gap: 10px; overflow-x: auto; padding: 2px 2px 6px;
          scrollbar-width: none; }
.rtiles::-webkit-scrollbar { display: none; }
.rtile { flex: 0 0 122px; border-radius: 18px; padding: 13px 12px 12px;
         border: 1px solid var(--line); background: var(--paper);
         box-shadow: var(--shadow); text-align: left; font: inherit;
         color: inherit; position: relative; }
.rtile.saving { border-color: var(--accent); }
.rtile .ic { width: 34px; height: 34px; border-radius: 11px;
             display: grid; place-items: center; font-size: 16px;
             margin-bottom: 18px; }
.rtile .ic.k-room { background: #eceff4; }
.rtile .ic.k-pass { background: #fdf3d9; }
.rtile .ic.k-studio { background: #f6ece2; }
.rtile .ic.k-wellness { background: #eef4ef; }
.rtile .ic.k-perk { background: #eceff4; }
.rtile .ic.k-event { background: #fdf3d9; }
.rtile .n { display: block; font-size: 12.5px; line-height: 1.3;
            min-height: 32px; }
.rtile .p { display: block; font-family: var(--serif); font-size: 15px;
            margin-top: 6px; font-variant-numeric: tabular-nums; }
.rtile .p small { display: block; font-family: var(--sans);
                  font-size: 10.5px; color: var(--muted); margin-top: 2px; }
.rpin { position: absolute; top: 10px; right: 10px; font-size: 9.5px;
        color: var(--warn); border: 1px solid currentColor;
        border-radius: 999px; padding: 1px 6px; }

/* saving ring */
.goalr { display: flex; align-items: center; gap: 16px; }
.goalr .ring { width: 62px; height: 62px; border-radius: 50%; flex: none;
               display: grid; place-items: center; }
.goalr .ring i { width: 46px; height: 46px; border-radius: 50%;
                 background: var(--paper); display: grid;
                 place-items: center; font-style: normal; font-size: 12.5px;
                 font-weight: 600; }
.goalr .t { font-size: 14.5px; font-weight: 500; }
.goalr .s { font-size: 12.5px; color: var(--muted); margin-top: 2px; }

/* iconed ledger rows (shared renderer) */
.jpc-ic { width: 38px; height: 38px; border-radius: 50%; display: grid;
          place-items: center; font-size: 15px; flex: none;
          font-style: normal; }
.jpc-ic.earn { background: #eef4ef; }
.jpc-ic.ref { background: #f6ece2; }
.jpc-ic.redeem { background: #fdf3d9; }
.jpc-ic.spend { background: #fdf3d9; }
.jpc-ic.back { background: var(--line-soft); }
.jpc-row { align-items: center; }
.jpc-tx .t { font-weight: 500; }

/* --------------------------------- circle, the rewards pass (R4 final) */
.segs { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px;
        background: var(--line-soft); border-radius: 999px; padding: 4px;
        margin: 2px 0 14px; }
.seg { border: 0; background: transparent; border-radius: 999px;
       padding: 9px 0; font-size: 12.5px; color: var(--ink-2);
       font-weight: 500; white-space: nowrap; }
.seg.on { background: var(--ink); color: var(--cream); }
.ccard-foot { display: flex; justify-content: space-between;
              align-items: center; margin-top: 14px; }
.ccard-ready { border: 0; background: var(--accent); color: var(--ink);
               border-radius: 999px; padding: 5px 11px; font-size: 12px;
               font-weight: 600; }
.rechip { display: flex; align-items: center; width: 100%; gap: 6px;
          border: 1px solid var(--line); background: var(--paper);
          border-radius: 999px; padding: 11px 16px; font-size: 13.5px;
          margin-bottom: 12px; text-align: left; color: var(--ink-2); }
.rechip .plus { color: var(--good); font-weight: 600; }
.rechip .chev { margin-left: auto; color: var(--muted); font-size: 16px; }
.gauge { position: relative; text-align: center; padding: 18px 16px 10px; }
.gauge svg { width: 200px; max-width: 70%; display: block; margin: 0 auto; }
.gauge-mid { position: absolute; left: 0; right: 0; top: 46%; }
.gauge-mid .n { font-family: var(--serif); font-size: 27px;
                font-variant-numeric: tabular-nums; }
.gauge-mid .l { font-size: 11px; color: var(--muted);
                text-transform: uppercase; letter-spacing: .08em;
                margin-top: 2px; }
.gauge-mid .togo { font-size: 12.5px; color: var(--warn); margin-top: 4px;
                   font-weight: 500; }
.gauge-ends { display: flex; justify-content: space-between;
              max-width: 76%; margin: -6px auto 0; font-size: 11px;
              color: var(--muted); font-variant-numeric: tabular-nums; }
.qacts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
         margin: 12px 0; }
.qact { border: 1px solid var(--line); background: var(--paper);
        border-radius: var(--r-md); padding: 12px 6px 10px;
        font-size: 12.5px; color: var(--ink); font-weight: 500; }
.qact span { display: block; font-size: 17px; margin-bottom: 5px; }
.way { display: flex; gap: 12px; align-items: center; padding: 12px 0;
       border-top: 1px solid var(--line-soft); }
.way:first-child { border-top: 0; }
.wic { width: 38px; height: 38px; border-radius: 50%; flex: none;
       background: var(--line-soft); display: grid; place-items: center;
       font-size: 16px; }
.wtx { flex: 1; min-width: 0; }
.wtx b { display: block; font-size: 14.5px; font-weight: 500; }
.wtx span { display: block; font-size: 12.5px; color: var(--muted);
            margin-top: 1px; }
.wval { font-family: var(--serif); font-size: 14px; color: var(--ink-2);
        white-space: nowrap; }
.rcard { position: relative; display: block; width: 100%; height: 150px;
         border: 0; border-radius: 20px; overflow: hidden;
         background-size: cover; background-position: center;
         box-shadow: var(--shadow-lift); margin-bottom: 12px;
         text-align: left; color: #f6f3ea; padding: 16px;
         font: inherit; }
.rcard .rc-body { position: absolute; left: 16px; right: 16px;
                  bottom: 14px; }
.rcard .rc-t { display: block; font-family: var(--serif); font-size: 19px;
               text-shadow: 0 1px 8px rgba(16,24,22,.5); }
.rcard .rc-p { display: block; font-size: 12.5px; margin-top: 3px;
               color: #e6e1d3; font-variant-numeric: tabular-nums; }
.rcard .rc-cta { position: absolute; right: 14px; top: 14px;
                 border-radius: 999px; padding: 7px 14px; font-size: 13px;
                 font-weight: 600; background: rgba(16,24,22,.55);
                 color: #f6f3ea; backdrop-filter: blur(6px);
                 -webkit-backdrop-filter: blur(6px); }
.rcard .rc-cta.gold { background: var(--accent); color: var(--ink); }
.rcard .rpin { position: absolute; left: 14px; top: 14px; font-size: 10.5px;
               background: rgba(16,24,22,.55); color: #f6f3ea;
               border-radius: 999px; padding: 3px 9px;
               backdrop-filter: blur(6px);
               -webkit-backdrop-filter: blur(6px); }

/* ------------------------------------------------ motion (R4, subtle) */
@property --p { syntax: "<percentage>"; inherits: false;
                initial-value: 0%; }
.goalr .ring { background: conic-gradient(var(--accent) 0 var(--p),
               var(--line-soft) var(--p) 100%);
               transition: --p var(--d-slow) var(--e-out); }
.gauge path[data-anim-gauge] { transition: stroke-dasharray var(--d-slow) var(--e-out); }
.mst-bar i { transition: width var(--d-slow) var(--e-out); }
.rcard.unlocked { animation: unlockGlow 1.6s ease 1; }
@keyframes unlockGlow {
  0% { box-shadow: var(--shadow-lift); transform: scale(.985); }
  35% { box-shadow: 0 0 0 4px rgba(255,200,56,.45), var(--shadow-lift);
        transform: scale(1.01); }
  100% { box-shadow: var(--shadow-lift); transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .goalr .ring, .gauge path[data-anim-gauge], .mst-bar i {
    transition: none; }
  .rcard.unlocked { animation: none; }
}

/* --------------------------------------------- the drawn icon family */
.jpi { width: 20px; height: 20px; display: block; fill: none;
       stroke: currentColor; stroke-width: 1.6; stroke-linecap: round;
       stroke-linejoin: round; }
.jpc-ic .jpi { width: 18px; height: 18px; }
.jpc-ic.earn { color: #2f7d5d; }
.jpc-ic.ref { color: #a9601c; }
.jpc-ic.redeem, .jpc-ic.spend { color: #8a6a14; }
.jpc-ic.back { color: var(--muted); }
.wic { color: var(--ink-2); }
.wic .jpi { width: 19px; height: 19px; }
.qact .jpi { margin: 0 auto 6px; color: var(--ink-2); }
.qact span { display: none; }

/* ------------------------------------------- the minted badge emblems */
.jpe { display: block; }
.jpc-ic.emb, .wic.emb { background: none; }
.jpc-ic.emb .jpe, .wic.emb .jpe { width: 100%; height: 100%; }
.qact .jpe { width: 42px; height: 42px; margin: 0 auto 7px; }

/* ------------------------------------------------- button refinement */
.btn { letter-spacing: .01em; font-weight: 600; }
.btn.sm { font-weight: 600; }
.seg { letter-spacing: .01em; }
.seg.on { font-weight: 600; }
.rc-cta { letter-spacing: .02em; }
.ccard-ready { letter-spacing: .02em; }
.qact { font-weight: 600; letter-spacing: .01em; color: var(--ink-2);
        transition: transform var(--d-tap) var(--e-out); }
.qact:active { transform: scale(var(--press-btn)); }
.rechip { font-weight: 500; }

/* ------------------------- the You rows (the Settings pattern, drawn) */
.frow { display: flex; align-items: center; gap: 13px; width: 100%;
        text-align: left; background: var(--paper);
        border: 1px solid var(--line); border-radius: var(--r-md);
        padding: 13px 14px; margin-bottom: 9px; font: inherit;
        color: inherit; text-decoration: none; box-shadow: var(--shadow);
        transition: transform var(--d-tap) var(--e-out); }
.frow:active { transform: scale(var(--press-row)); }
.fic { width: 38px; height: 38px; border-radius: 50%; flex: none;
       background: var(--line-soft); display: grid; place-items: center;
       color: var(--ink-2); }
.fic .jpi { width: 19px; height: 19px; }
.ftx { flex: 1; min-width: 0; }
.ftx b { display: block; font-size: 15px; font-weight: 600;
         letter-spacing: -.01em; }
.ftx small { display: block; font-size: 12.5px; color: var(--muted);
             margin-top: 2px; }
.fchev { color: #b7b3a7; font-size: 20px; line-height: 1; flex: none; }
.frow.danger .ftx b { color: #b42318; }
.frow.danger .fic { color: #b42318; }

/* the file pickzone: never a naked native input */
.pickzone { display: block; width: 100%; text-align: center;
            background: transparent; border: 1.6px dashed #c9c4b4;
            border-radius: var(--r-lg); padding: 22px 16px 18px;
            font: inherit; color: inherit;
            transition: border-color var(--d-tap) var(--e-out),
                        transform var(--d-tap) var(--e-out); }
.pickzone:active { transform: scale(var(--press-row)); }
.pickzone.has { border-style: solid; border-color: var(--accent);
                background: var(--paper); }
.pz-ic { display: block; margin: 0 auto 8px; width: 38px; height: 38px;
         border-radius: 50%; background: var(--line-soft);
         color: var(--ink-2); display: grid; place-items: center;
         margin-left: auto; margin-right: auto; }
.pz-ic .jpi { width: 19px; height: 19px; }
.pz-t { display: block; font-size: 15.5px; font-weight: 600; }
.pz-s { display: block; font-size: 12.5px; color: var(--muted);
        margin-top: 4px; line-height: 1.45; }

/* upload progress + the held moment */
.btn .upbar { display: block; height: 4px; border-radius: 999px;
              background: rgba(244,240,231,.25); margin-bottom: 7px;
              overflow: hidden; }
.btn .upbar i { display: block; height: 100%; width: 0%;
                background: var(--accent); border-radius: 999px;
                transition: width var(--d-tap) var(--e-out); }
.heldic { width: 54px; height: 54px; border-radius: 50%;
          background: var(--accent); display: inline-grid;
          place-items: center; color: var(--ink); }
.heldic .jpi { width: 26px; height: 26px; }

/* the range steppers on the release sheet */
.rng { display: flex; align-items: center; justify-content: center;
       gap: 12px; margin: 12px 0 4px; }
.rng-sep { color: var(--muted); font-size: 13px; }
.stp { display: inline-flex; align-items: center; gap: 2px;
       border: 1px solid var(--line); border-radius: 999px;
       background: var(--paper); padding: 2px; }
.stp button { width: 34px; height: 34px; border: 0; background: none;
              font-size: 19px; color: var(--ink-2); border-radius: 50%; }
.stp button:active { background: var(--line-soft); }
.stp b { min-width: 26px; text-align: center; font-size: 15px;
         font-variant-numeric: tabular-nums; }

/* the page strip: small honest previews, tap first and last to range */
.pgstrip { display: flex; gap: 8px; overflow-x: auto; padding: 4px 2px 6px;
           margin: 2px 0 0; -webkit-overflow-scrolling: touch;
           scrollbar-width: none; }
.pgstrip::-webkit-scrollbar { display: none; }
.pgthumb { position: relative; flex: 0 0 auto; width: 52px; height: 68px;
           border: 1.5px solid var(--line); border-radius: 8px;
           background: var(--paper); padding: 0; overflow: hidden;
           opacity: .55; transition: opacity var(--d-tap) var(--e-out),
                                     border-color var(--d-tap) var(--e-out),
                                     transform var(--d-tap) var(--e-out); }
.pgthumb img { position: absolute; inset: 0; width: 100%; height: 100%;
               object-fit: cover; object-position: top; }
.pgthumb .pgn { position: absolute; right: 3px; bottom: 3px;
                font-size: 10px; line-height: 1; padding: 3px 5px;
                border-radius: 6px; background: var(--card);
                color: var(--muted); border: 1px solid var(--line-soft); }
.pgthumb.sel { opacity: 1; border-color: var(--accent);
               transform: translateY(-1px); }
.pgthumb.sel .pgn { color: var(--ink); border-color: var(--accent); }
/* .pgsmore, not .pgmore: the pagination button further down this sheet
   already owns that name, and being later it won — the strip's quiet
   "+2 more" label came out as a full-width bordered pill, shoved off the
   right edge of a row of 52px thumbnails. */
.pgsmore { flex: 0 0 auto; align-self: center; color: var(--muted);
           font-size: 12px; padding: 0 6px; }
.pgstrip-hint { text-align: center; margin: 6px 0 2px; }

/* rows on the Printing card: name above, quiet detail below */
.mrow { padding: 10px 0; }
.mrow + .mrow { border-top: 1px solid var(--line-soft); }
.mrow .l b { display: block; font-size: 15px; }
.mrow .l .v { display: block; margin-top: 2px; font-size: 13px;
              color: var(--muted); }
.mrow .meter { margin-top: 8px; }

/* The whole print queue, in its own sheet. Forty documents scroll here,
   inside a fixed frame, instead of stretching the Today screen: the card
   states what is waiting, this is where you work through it. */
.pqtop { display: flex; align-items: baseline; justify-content: space-between;
         margin: 0 0 8px; padding: 0 2px; }
.pqtop .sub { margin: 0; font-size: 13px; }
.pqlist { padding: 2px 14px; max-height: 46dvh; overflow-y: auto;
          overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
.pqrow { display: flex; align-items: flex-start; gap: 12px;
         padding: 11px 0; cursor: pointer; }
.pqrow + .pqrow { border-top: 1px solid var(--line-soft); }
.pqbox {
  flex: 0 0 auto; width: 22px; height: 22px; margin-top: 1px;
  border: 1.5px solid var(--line); border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  font-size: 13px; color: var(--accent-ink); background: var(--paper);
  transition: background var(--d-tap) var(--e-out),
              border-color var(--d-tap) var(--e-out);
}
.pqrow.on .pqbox { background: var(--accent); border-color: var(--accent); }
.pqtx { min-width: 0; }
.pqtx b { display: block; font-size: 15px; font-weight: 500;
          overflow-wrap: anywhere; }
.pqtx small { display: block; margin-top: 2px; font-size: 13px;
              color: var(--muted); }
.pqbulk { display: flex; gap: 8px; margin-top: 12px; }
.pqbulk .btn { flex: 1; margin-top: 0; }

/* the full-screen page reader: swipe between pages, range rides along */
.pgview { position: fixed; inset: 0; z-index: 90; background: var(--cream);
          display: flex; flex-direction: column; opacity: 0;
          transition: opacity var(--d-tap) var(--e-out); }
.pgview.in { opacity: 1; }
.pgv-top { display: flex; align-items: center; justify-content: center;
           position: relative; padding: 14px 18px;
           padding-top: calc(14px + env(safe-area-inset-top, 0px)); }
.pgv-count { font-size: 14px; color: var(--muted);
             font-variant-numeric: tabular-nums; }
.pgv-done { position: absolute; right: 12px; top: 50%;
            transform: translateY(-50%);
            margin-top: calc(env(safe-area-inset-top, 0px) / 2);
            border: 0; background: none; font-size: 16px; font-weight: 650;
            color: var(--ink); padding: 8px 10px; }
.pgv-track { flex: 1; display: flex; overflow-x: auto; overflow-y: hidden;
             scroll-snap-type: x mandatory;
             -webkit-overflow-scrolling: touch; scrollbar-width: none; }
.pgv-track::-webkit-scrollbar { display: none; }
.pgv-slide { flex: 0 0 100%; scroll-snap-align: center; display: grid;
             place-items: center; padding: 6px 14px 12px; position: relative; }
.pgv-slide img { max-width: 100%; max-height: 100%; object-fit: contain;
                 border-radius: 6px; background: #fff;
                 box-shadow: 0 8px 30px rgba(26, 24, 18, .16); }
.pgv-ghost { position: absolute; font-size: 44px; color: var(--line);
             font-weight: 700; z-index: -1; }
.pgv-bar { padding: 12px 18px;
           padding-bottom: calc(14px + env(safe-area-inset-bottom, 0px));
           border-top: 1px solid var(--line-soft); }
.pgv-deal { margin: 0 0 10px; text-align: center; font-size: 13px;
            color: var(--muted); }
.pgv-acts { display: flex; gap: 10px; justify-content: center; }
.pgv-all { display: block; margin: 10px auto 0; border: 0;
           background: none; font-size: 13px; color: var(--ink-2);
           text-decoration: underline; text-underline-offset: 3px; }
.pgv-pill { flex: 1; max-width: 220px; padding: 11px 12px;
            border: 1.5px solid var(--line); border-radius: 999px;
            background: var(--paper); color: var(--ink); font-size: 14px;
            font-weight: 600; transition: border-color var(--d-tap) var(--e-out),
                                          background var(--d-tap) var(--e-out); }
.pgv-pill.on { border-color: var(--ink); background: var(--ink);
               color: var(--paper); }

/* the pick circle on each page thumb: tap to keep or skip that page */
.pgtick { position: absolute; top: 3px; right: 3px; width: 24px;
          height: 24px; border-radius: 50%; z-index: 2;
          border: 1.5px solid var(--line); background: var(--paper);
          display: grid; place-items: center; }
.pgtick::before { content: ""; position: absolute; inset: -9px; }
.pgtick::after { content: ""; width: 10px; height: 6px;
                 border-left: 2px solid transparent;
                 border-bottom: 2px solid transparent;
                 transform: rotate(-45deg) translate(1px, -1px); }
.pgthumb.sel .pgtick { background: var(--accent);
                       border-color: var(--accent); }
.pgthumb.sel .pgtick::after { border-color: var(--ink); }
.pgthumb .pgn { right: auto; left: 3px; }

/* the chosen-files list on the upload sheet */
[data-pflist] .jpc-line { gap: 10px; align-items: center; }
[data-pflist] .jpc-line span { flex: 1; min-width: 0; overflow: hidden;
                               text-overflow: ellipsis;
                               white-space: nowrap; }
.pf-x { width: 26px; height: 26px; border: 0; border-radius: 50%;
        background: var(--line-soft); color: var(--ink-2);
        font-size: 16px; line-height: 1; flex: 0 0 auto; }
.pf-x:active { background: var(--line); }

/* a scattered pick may take two lines; the label holds its ground */
.jpc-line.pgrow { gap: 12px; }
.jpc-line.pgrow b { text-align: right; overflow-wrap: anywhere;
                    min-width: 0; }

/* the small in-button working ring */
.btnspin { display: inline-block; width: 13px; height: 13px;
           margin-right: 7px; vertical-align: -2px;
           border: 2px solid currentColor; border-top-color: transparent;
           border-radius: 50%; opacity: .7;
           animation: btnspin .7s linear infinite; }
@keyframes btnspin { to { transform: rotate(360deg); } }

/* the wallet card: stored dollars, plainly stated */
.wcard .wbal { display: flex; align-items: baseline;
               justify-content: space-between; }
.wcard .wbal small { font-size: 13px; color: var(--muted);
                     letter-spacing: .04em; text-transform: uppercase; }
.wcard .wbal b { font-size: 30px; font-weight: 650;
                 font-variant-numeric: tabular-nums; }
.winput { width: 100%; padding: 13px 14px; font-size: 17px;
          border: 1.5px solid var(--line); border-radius: var(--r-sm);
          background: var(--paper); color: var(--ink); }
.winput:focus { outline: none; border-color: var(--accent); }

/* ------------------------------------------------ the profile card */
/* One tall card in the Raya grammar: face first, name and chips on an
   ink scrim. Before a photo it is the same card on cream, and every
   affordance on it opens the same photos sheet. */
.lic { fill: none; stroke: currentColor; stroke-width: 1.7;
       stroke-linecap: round; stroke-linejoin: round; }
.pcard { position: relative; border-radius: var(--r-lg); overflow: hidden;
         box-shadow: var(--shadow-lift); aspect-ratio: 4 / 5;
         margin-bottom: 10px; background: var(--paper);
         border: 1px solid var(--line); }
.pcard > img { position: absolute; inset: 0; width: 100%; height: 100%;
               object-fit: cover; }
.pcbar { position: absolute; top: 12px; left: 14px; right: 14px;
         display: flex; gap: 5px; z-index: 3; pointer-events: none; }
.pcbar i { flex: 1; height: 3px; border-radius: 999px;
           background: rgba(255,255,255,.38); }
.pcbar i.on { background: #fff; }
.pcpg { position: absolute; top: 0; bottom: 0; width: 44%; z-index: 2;
        border: 0; background: transparent; padding: 0; }
.pcpg.l { left: 0; } .pcpg.r { right: 0; }
/* The two tools live in one cluster in the top corner. Nothing sits
   over the chips any more, so a five interest row reads as five. */
/* 22px, not 12: with more than one photo the story pager is a bar
   across the top of the card at 12px, and a pill parked on top of it
   would hide which photo you are looking at. */
.pctools { position: absolute; top: 22px; right: 13px; z-index: 4;
           display: flex; align-items: center; gap: 8px; }
.pcedit, .pccam { color: #fff; background: rgba(16,24,22,.34);
                  border: 1px solid rgba(255,255,255,.28);
                  border-radius: 999px; backdrop-filter: blur(8px);
                  -webkit-backdrop-filter: blur(8px);
                  transition: transform var(--d-tap) var(--e-out); }
.pcedit { font-size: 13.5px; font-weight: 600; padding: 8px 15px; }
.pccam { width: 36px; height: 36px; display: grid; place-items: center; }
.pccam svg { width: 18px; height: 18px; }
.pcedit:active, .pccam:active { transform: scale(var(--press-ico)); }
/* The bare card has no scrim to sit on, so the pill is drawn on cream
   and its own corner is enough; it keeps its old place. */
.pcedit.onbare { position: absolute; top: 22px; right: 14px; z-index: 4;
                 color: var(--ink); background: transparent;
                 border-color: var(--line); }
/* Shorter than it was: without the nameplate the scrim only has to
   carry two lines, and a taller gradient would darken the face. */
.pcscrim { position: absolute; inset: auto 0 0 0; padding: 54px 16px 14px;
           z-index: 1; color: #fff;
           background: linear-gradient(to top, rgba(16,24,22,.80),
                       rgba(16,24,22,.34) 58%, transparent); }
.pcname { font-family: var(--serif); font-size: 32px; letter-spacing: -.2px;
          line-height: 1.05; }
/* On your own card this is the only line, so it carries the weight the
   nameplate used to; on theirs it still sits under a name. */
.pcline { font-size: 15px; margin-top: 2px; font-weight: 500;
          line-height: 1.35; }
.pcname + .pcline { font-size: 14px; opacity: .82; font-weight: 400;
                    margin-top: 4px; }
/* One row that scrolls, never a wrapped block: the chips are a strip
   you push, and it fades at the edge so a cut chip reads as "more"
   rather than as a clipped one. */
.pctags { display: flex; gap: 5px; margin: 11px -16px 0; padding: 0 16px;
          overflow-x: auto; scrollbar-width: none;
          -webkit-overflow-scrolling: touch;
          -webkit-mask-image: linear-gradient(90deg, #000 80%, transparent);
          mask-image: linear-gradient(90deg, #000 80%, transparent); }
.pctags::-webkit-scrollbar { display: none; }
.pctags span { font-size: 12px; color: #fff; border-radius: 999px;
               padding: 3px 10px; border: 1px solid rgba(255,255,255,.34);
               background: rgba(255,255,255,.14); white-space: nowrap;
               backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px); }

.pcard.pcbare { display: flex; flex-direction: column; align-items: center;
                justify-content: center; background: var(--cream);
                text-align: center; padding: 26px 22px; }
.pcwm { position: absolute; inset: 0; display: grid; place-items: center;
        opacity: .05; pointer-events: none; }
.pcwm svg { width: 62%; height: auto; }
.pcwm svg path { fill: var(--ink); }
.pcmono { position: relative; width: 96px; height: 96px; border-radius: 50%;
          background: var(--paper); border: 1px solid var(--line);
          display: grid; place-items: center; font-family: var(--serif);
          font-size: 40px; color: var(--ink-2); box-shadow: var(--shadow);
          padding: 0; }
.pcbadge { position: absolute; right: -4px; bottom: -2px; width: 30px;
           height: 30px; border-radius: 50%; background: var(--accent);
           border: 2px solid var(--cream); display: grid;
           place-items: center; color: var(--accent-ink); }
.pcbadge svg { width: 15px; height: 15px; }
.pcbname { font-family: var(--serif); font-size: 26px; margin-top: 14px;
           position: relative; }
.pcbmail { font-size: 13px; color: var(--muted); margin-top: 3px;
           position: relative; }
.pcbtags { justify-content: center; position: relative; margin-top: 12px; }
.pcbcta { width: 78%; margin-top: 22px; position: relative; }
.pcbfine { position: relative; color: var(--muted); font-size: 12.5px;
           margin-top: 12px; }

/* ------------------------------------------------- the photos sheet */
.phgrid { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 8px;
          margin-bottom: 6px; }
.pht { position: relative; aspect-ratio: 4 / 5; border-radius: 12px;
       overflow: hidden; border: 1px solid var(--line); padding: 0;
       background: var(--ground); }
.pht img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pht.sel { outline: 2.5px solid var(--accent); outline-offset: 1px; }
.phcover { position: absolute; left: 6px; top: 6px; font-size: 10px;
           letter-spacing: .08em; font-weight: 600;
           background: var(--accent); color: var(--accent-ink);
           border-radius: 999px; padding: 3px 8px; }
.phadd { aspect-ratio: 4 / 5; border: 1.5px dashed var(--line);
         border-radius: 12px; display: grid; place-items: center;
         color: var(--muted); background: transparent; }
.phadd svg { width: 22px; height: 22px; }
.phacts { display: flex; gap: 8px; justify-content: center;
          margin: 4px 0 8px; }
.phacts .danger { color: var(--warn); border-color: var(--warn); }
.ptogrow { display: flex; align-items: center; gap: 12px;
           padding: 12px 2px 4px; text-align: left; }
.ptogrow .ptx { flex: 1; }
.ptogrow .ptx b { font-size: 14.5px; font-weight: 500; display: block; }
.ptogrow .ptx small { font-size: 12.5px; color: var(--muted); }
.pswitch { width: 46px; height: 28px; border-radius: 999px;
           background: var(--line); position: relative; flex: none;
           border: 0; padding: 0; transition: background var(--d-tap) var(--e-out); }
.pswitch i { position: absolute; top: 3px; left: 3px; width: 22px;
             height: 22px; border-radius: 50%; background: #fff;
             box-shadow: 0 1px 3px rgba(23,23,22,.25);
             transition: transform var(--d-tap) var(--e-out); }
.pswitch.on { background: var(--ink); }
.pswitch.on i { transform: translateX(18px); }
.phfine { color: var(--muted); font-size: 12.5px; margin: 6px 2px 12px;
          text-align: left; line-height: 1.5; }

/* --------------------------------------------- the floor, redrawn */
.raise-mark { width: 26px; height: auto; }
.raise-mark path { fill: var(--ink); }
.vows { display: flex; justify-content: center; gap: 16px;
        margin-top: 14px; flex-wrap: wrap; }
.vow { display: inline-flex; align-items: center; gap: 5px;
       color: var(--muted); font-size: 12px; }
.vow svg { width: 14px; height: 14px; }
.qboard { text-align: center; padding: 24px 18px 22px; }
.ghosts { display: flex; justify-content: center; margin-bottom: 12px; }
.ghosts i { width: 40px; height: 40px; border-radius: 50%;
            border: 1.5px dashed #cfcabb; background: var(--cream);
            margin-left: -10px; }
.ghosts i:first-child { margin-left: 0; }
.ghosts.solid i { border-style: solid; border-color: var(--line);
                  background: var(--ground); }
.qboard b { display: block; font-family: var(--serif); font-weight: 400;
            font-size: 17px; }
.qboard small { color: var(--muted); font-size: 13px; margin-top: 3px;
                display: block; }
.sectbtn { margin-left: auto; display: inline-flex; align-items: center;
           gap: 5px; border: 1px solid var(--ink); background: var(--paper);
           border-radius: 999px; padding: 6px 13px; font-size: 13px;
           font-weight: 500; box-shadow: 0 1px 2px rgba(23,23,22,.05); }
.sectbtn svg { width: 12px; height: 12px; }
.card.ex { display: block; width: 100%; text-align: left;
           background: transparent; box-shadow: none;
           border: 1px dashed var(--line); }
.exbrow { display: block; font-size: 10.5px; letter-spacing: .12em;
          color: var(--muted); font-weight: 600; margin-bottom: 8px; }
.exq { display: block; font-family: var(--serif); font-size: 16.5px;
       font-style: italic; line-height: 1.35; color: var(--ink-2); }
.exby { display: flex; align-items: center; gap: 8px; margin-top: 10px;
        color: var(--muted); font-size: 12.5px; }
.av.s { width: 26px; height: 26px; font-size: 12px; }
.exph { display: block; border-radius: 12px; overflow: hidden;
        margin-bottom: 10px; aspect-ratio: 16 / 9.5;
        border: 1px solid var(--line); }
.exph img { width: 100%; height: 100%; object-fit: cover; display: block; }
.excap { display: block; font-family: var(--serif); font-size: 15.5px;
         font-style: normal; }
/* ========================================================== the post
   Instagram's grammar in the house's hand, shipped 2026-08-17 on
   Fahad's ask. One card per post, media edge to edge at the photo's own
   ratio (the server sends it, so nothing jumps once the bytes land), one
   action bar, a caption that leads with the first name. The ember is the
   ONLY new hue in the app and it exists for exactly one job: a filled
   heart. It is deliberately not the gold, which in this app means money.
   Depth: jasper kb/floor.md. */
.post {
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow);
  margin-bottom: 14px; overflow: hidden;
}
.post.insheet { box-shadow: none; margin: 0 0 14px; }
.phd { display: flex; align-items: center; gap: 11px; padding: 13px 14px 12px; }
.phd .av { width: 38px; height: 38px; font-size: 15px; }
.phw { min-width: 0; flex: 1; }
.pnm {
  font-size: 14.5px; font-weight: 600; letter-spacing: -.005em;
  color: var(--ink); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis;
}
.pkind {
  font-size: 10.5px; font-weight: 600; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); margin-top: 3px;
}
.pmore {
  margin-left: auto; flex: none; background: none; border: 0;
  padding: 8px 4px 8px 12px; line-height: 0; color: var(--muted);
}
.pmore svg { width: 18px; height: 18px; }

.pmedia {
  display: block; width: 100%; padding: 0; border: 0; line-height: 0;
  background: var(--cream); aspect-ratio: 1 / 1;
  border-top: 1px solid var(--line-soft);
  border-bottom: 1px solid var(--line-soft);
}
.pmedia img { width: 100%; height: 100%; object-fit: cover; display: block; }

.pact { display: flex; align-items: center; padding: 7px 8px 1px; }
.pact button {
  background: none; border: 0; padding: 9px; line-height: 0;
  border-radius: 999px;
  transition: transform var(--d-tap) var(--e-out);
}
.pact button:active { transform: scale(var(--press-ico)); }
.pact svg {
  width: 24px; height: 24px; fill: none; stroke: var(--ink);
  stroke-width: 1.65; stroke-linecap: round; stroke-linejoin: round;
}
/* Only the cup's body fills (the .cf path); the handle and the steam
   stay drawn lines, or the glyph becomes a blob. */
.pact .plike.on svg { stroke: var(--ember); }
.pact .plike.on svg .cf { fill: var(--ember); }
.pact .pboost.on svg { stroke: var(--warn); }
.pact .pfwd { margin-left: auto; }
/* The tap has to feel like it landed before the network answers. */
.pact button.pop svg { animation: heartpop .34s var(--e-pop); }
/* Three gold flecks burst off a fresh cup: celebration, six pixels of
   it, gone in half a second. */
.pact .plike { position: relative; }
.pact .plike .flk { position: absolute; border-radius: 50%;
                    background: var(--accent); opacity: 0;
                    pointer-events: none; }
.pact .plike .flk.f1 { width: 5px; height: 5px; top: 7px; right: 5px; }
.pact .plike .flk.f2 { width: 4px; height: 4px; top: 13px; right: 1px; }
.pact .plike .flk.f3 { width: 3px; height: 3px; top: 3px; right: 13px; }
.pact .plike.pop .flk.f1 { animation: flkpop .5s ease-out .05s; }
.pact .plike.pop .flk.f2 { animation: flkpop .5s ease-out .12s; }
.pact .plike.pop .flk.f3 { animation: flkpop .5s ease-out 0s; }
@keyframes flkpop {
  0% { opacity: 0; transform: none; }
  30% { opacity: 1; }
  100% { opacity: 0; transform: translate(7px, -15px) scale(.5); }
}
@keyframes heartpop {
  0% { transform: scale(1); } 45% { transform: scale(1.28); }
  100% { transform: scale(1); }
}

.pbody { padding: 3px 16px 15px; }
.pbody.nomedia { padding: 0 16px 4px; }
.pbody.tight { padding: 2px 16px 15px; }
.pcap { font-size: 14.5px; line-height: 1.46; color: var(--ink-2); }
.pcap b { font-weight: 600; color: var(--ink); }
.psig {
  display: flex; align-items: center; gap: 7px; background: none;
  border: 0; padding: 9px 0 0; font-size: 13px; color: var(--ink-2);
  text-align: left; width: 100%;
}
.psig svg {
  width: 15px; height: 15px; flex: none; fill: none; stroke: var(--muted);
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.plikes .psig svg { stroke: var(--ember); }
.plikes .psig svg .cf { fill: var(--ember); }

/* The byline a lifted post wears, above the header: quiet, amber, and
   it names the person whose taste put it there. */
.pboostline { padding: 0 16px; }
.pboostline .psig { padding: 12px 0 0; font-size: 12.5px;
                    color: var(--muted); }
.pboostline .psig svg { stroke: var(--warn); }
.pboostline .psig b { color: var(--ink-2); }
.psig b { font-weight: 600; }
.pall, .padd {
  display: block; background: none; border: 0; padding: 8px 0 0;
  font-size: 13.5px; color: var(--muted); text-align: left;
}
.pcmt { font-size: 14px; line-height: 1.45; color: var(--ink-2);
        margin-top: 6px; }
.pcmt b { font-weight: 600; color: var(--ink); }
.pwhen {
  font-size: 10.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--muted); margin-top: 11px;
}

/* the comment thread, in a sheet */
.cmts { max-height: 46vh; overflow: auto; margin-bottom: 14px; }
.crow { display: flex; align-items: flex-start; gap: 10px;
        padding: 11px 0; border-bottom: 1px solid var(--line-soft); }
.crow:last-child { border-bottom: 0; }
.cbd { flex: 1; min-width: 0; font-size: 14.5px; line-height: 1.45;
       display: block; overflow-wrap: anywhere; }
.cbd b { font-weight: 600; }
.cbd .av.s { display: inline-grid; vertical-align: middle;
             margin-right: 8px; }
.cdel { background: none; border: 0; padding: 4px; line-height: 0;
        color: var(--muted); flex: none; }
.cdel svg { width: 16px; height: 16px; }

/* ======================================================= member pages
   Your body of work, and everyone else's (2026-08-17, Fahad's ask). The
   grid is Instagram's shape because that is the object people already
   know how to read. The TEXT TILE is ours and it is not decoration:
   four of the five post kinds can arrive with no photo, and a grid of
   blank squares would say less than the words themselves. Tiles carry
   no dates and no counts, the same discipline as the cards. */
.pstats {
  display: flex; align-items: baseline; gap: 14px; margin: 14px 2px 0;
  font-size: 13px; color: var(--muted);
}
.pstats b { font-size: 15px; color: var(--ink); font-weight: 600; }
.pgrid {
  display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 3px;
  margin: 12px 0 4px; border-radius: var(--r-md); overflow: hidden;
}
.ptile {
  position: relative; aspect-ratio: 1 / 1; padding: 0; border: 0;
  background: var(--cream); overflow: hidden; display: block;
}
.ptile img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* NOTE, worth keeping: -webkit-line-clamp needs its element to be a
   plain block. A flex item and an absolutely positioned box are both
   BLOCKIFIED, so `display:-webkit-box` computes to flow-root and the
   clamp is silently ignored. That is why the tile is not a flex column
   and why the photo caption clamps on an inner span. */
.ptile.txt {
  padding: 9px 9px 10px; text-align: left; display: block;
  border: 1px solid var(--line-soft);
}
.ptile .tk {
  display: block; font-size: 8.5px; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 5px;
}
.ptile .tb {
  font-family: var(--serif); font-size: 12.5px; line-height: 1.32;
  color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 5;
  -webkit-box-orient: vertical; overflow: hidden;
}
/* a photo post's words ride the picture, so the grid still says what it
   was about. ONE line: the tile is ~124px on a phone and two lines of
   11px over a photograph is noise, not information. */
.ptile .tsc {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 8px 7px;
  background: linear-gradient(to top, rgba(23,23,22,.78), transparent);
  color: #fff; font-size: 11px; line-height: 1.3; text-align: left;
}
.ptile .tsc > span {
  display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical;
  overflow: hidden;
}
.pgmore {
  width: 100%; background: none; border: 1px solid var(--line);
  border-radius: 999px; padding: 10px; font-size: 14px; color: var(--ink-2);
  margin-top: 10px;
}
.pback {
  display: flex; align-items: center; gap: 8px; background: none;
  border: 0; padding: 2px 0 12px; font-size: 14.5px; color: var(--muted);
}
.pback svg { width: 17px; height: 17px; fill: none; stroke: currentColor;
             stroke-width: 1.8; stroke-linecap: round;
             stroke-linejoin: round; }
.pcta { display: flex; gap: 8px; margin-top: 14px; }
.pcta .btn { flex: 1; }
/* the name and the face are the door to a page, in a post header and on
   a board card alike */
.phlink { background: none; border: 0; padding: 0; text-align: left;
          min-width: 0; flex: 1; }
.fcard > .phlink, .fbd > .phlink { display: block; width: 100%; }


/* ===================================================== the Making tab
   The social section proper (2026-08-19). The faces strip is the
   open-to-meet board wearing Instagram's story grammar: gold ring =
   hand up right now, same expiry, same vows, nothing new leaks. */
.vhead { display: flex; align-items: baseline; gap: 10px; margin: 0 0 12px; }
.vhead h1 { margin: 0; }
.vbell { margin-left: auto; position: relative; background: none; border: 0;
         padding: 6px; line-height: 0; align-self: center; }
.vbell svg { width: 24px; height: 24px; fill: none; stroke: var(--ink);
             stroke-width: 1.7; stroke-linecap: round;
             stroke-linejoin: round; }
.vbell i { position: absolute; top: 3px; right: 2px; min-width: 16px;
           height: 16px; border-radius: 999px; background: var(--ember);
           color: #fff; font-size: 10px; font-weight: 700;
           font-style: normal; display: grid; place-items: center;
           padding: 0 4px; border: 2px solid var(--cream); }

.vstrip { display: flex; gap: 14px; overflow-x: auto; padding: 4px 2px 2px;
          margin: 0 0 6px; scrollbar-width: none; }
.vface { display: flex; flex-direction: column; align-items: center;
         gap: 6px; background: none; border: 0; padding: 0; flex: none;
         width: 66px; }
.vring { width: 62px; height: 62px; border-radius: 50%; padding: 3px;
         background: linear-gradient(135deg, var(--accent), #e8a112);
         display: block; }
.vring.quiet { background: var(--line); }
.vring .av { width: 100%; height: 100%; font-size: 20px;
             border: 2.5px solid var(--paper); }
.vface small { font-size: 11px; color: var(--ink-2); white-space: nowrap;
               overflow: hidden; text-overflow: ellipsis; max-width: 66px; }
.vface .vyou { width: 62px; height: 62px; border-radius: 50%;
               border: 1.5px dashed var(--muted); display: grid;
               place-items: center; color: var(--muted); }
.vface .vyou svg { width: 22px; height: 22px; fill: none;
                   stroke: currentColor; stroke-width: 1.8;
                   stroke-linecap: round; }
.vstripnote { font-size: 11px; color: var(--muted); margin: 0 2px 14px; }

.vcomposer { display: flex; align-items: center; gap: 11px; width: 100%;
             background: var(--paper); border: 1px solid var(--line);
             border-radius: 999px; padding: 9px 9px 9px 16px;
             box-shadow: var(--shadow); margin-bottom: 14px; }
.vcomposer span { color: var(--muted); font-size: 14.5px; flex: 1;
                  text-align: left; }
.vcomposer b { background: var(--ink); color: var(--cream); font-size: 13px;
               font-weight: 500; border-radius: 999px; padding: 8px 14px; }

/* the follow chip in a card header: warm, quiet once done */
.vfollow { background: none; border: 0; color: var(--warn);
           font-size: 13.5px; font-weight: 600; padding: 4px 0 4px 10px;
           flex: none; }
.vfollow.on, .vfollow[disabled] { color: var(--muted); font-weight: 500;
                                  opacity: 1; pointer-events: none; }

/* the sorted line on a card */
.psig.psort { color: var(--good); }
.psig.psort svg { stroke: var(--good); }
.psig.psort b { color: var(--good); }
.note-follow { font-size: 12.5px; color: var(--muted);
               margin: 10px 2px 4px; line-height: 1.5; }

/* the bell rows, shared with While you were out and Sorted deeds */
.arow { display: flex; align-items: center; gap: 12px; padding: 13px 0;
        border-bottom: 1px solid var(--line-soft); }
.arow:last-child { border-bottom: 0; }
.arow .aic { width: 38px; height: 38px; border-radius: 50%; flex: none;
             display: grid; place-items: center; background: var(--ground);
             border: 1px solid var(--line); }
.arow .aic svg { width: 18px; height: 18px; fill: none;
                 stroke: var(--ink-2); stroke-width: 1.7;
                 stroke-linecap: round; stroke-linejoin: round; }
.arow .aic.love { background: #faeae6; border-color: #efd0c8; }
.arow .aic.love svg { fill: var(--ember); stroke: var(--ember); }
.arow .abd { flex: 1; min-width: 0; font-size: 14px; line-height: 1.42; }
.arow .abd b { font-weight: 600; }
.arow .awhen { color: var(--muted); font-size: 12px; margin-top: 2px; }
.arow .athumb { width: 40px; height: 40px; border-radius: 8px; flex: none;
                object-fit: cover; border: 1px solid var(--line); }
.arow .btn.sm { flex: none; }


/* ================================================== the craft layer
   (2026-08-19, after Fahad's "still feels too mickey mouse"). Motion
   and materials, not decoration: navigation animates, images arrive
   choreographed, everything tappable answers the finger. */

/* --- navigation transitions. The chrome and the tab bar carry their
   own names so they hold still while the screen moves under them,
   exactly like a native navigation stack. Tab switches are INSTANT on
   purpose (native tab bars do not animate); only push/pop shapes move.
   The names apply only while html[data-vt] is up (set just before
   startViewTransition, cleared after finished, so both captures see
   them): iOS Safari un-fixes a position:fixed element that carries a
   permanent view-transition-name, and the tab bar scrolled away with
   the page. */
html[data-vt] .chrome { view-transition-name: floor-chrome; }
html[data-vt] .tabs { view-transition-name: floor-tabs; }
::view-transition-group(floor-chrome),
::view-transition-group(floor-tabs) { animation: none; }
::view-transition-old(floor-chrome), ::view-transition-old(floor-tabs)
  { animation: none; opacity: 0; }
::view-transition-new(floor-chrome), ::view-transition-new(floor-tabs)
  { animation: none; opacity: 1; }
html[data-vt] ::view-transition-old(root),
html[data-vt] ::view-transition-new(root) {
  animation-duration: 300ms;
  animation-timing-function: cubic-bezier(.32, .72, 0, 1);
}
@keyframes vt-in-right { from { transform: translateX(100%); } }
@keyframes vt-out-left { to { transform: translateX(-28%);
                              opacity: .6; } }
@keyframes vt-in-left { from { transform: translateX(-28%);
                               opacity: .6; } }
@keyframes vt-out-right { to { transform: translateX(100%); } }
html[data-vt="push"]::view-transition-new(root)
  { animation-name: vt-in-right;
    box-shadow: -12px 0 32px rgba(23, 23, 22, .14); }
html[data-vt="push"]::view-transition-old(root)
  { animation-name: vt-out-left; }
html[data-vt="pop"]::view-transition-new(root)
  { animation-name: vt-in-left; }
html[data-vt="pop"]::view-transition-old(root)
  { animation-name: vt-out-right; z-index: 1;
    box-shadow: -12px 0 32px rgba(23, 23, 22, .14); }

/* --- everything tappable answers the finger at pointerdown --- */
.frow:active, .pmrow:active, .arow:active, .ptile:active,
.vface:active, .crow2 .av:active, .vcomposer:active
  { transform: scale(var(--press-row)); }
.frow, .pmrow, .arow, .ptile, .vface, .vcomposer
  { transition: transform var(--d-tap) var(--e-out); }
.pmedia:active img { transform: scale(var(--press-row)); }
.pmedia img { transition: transform var(--d-tap) var(--e-out); }
/* kill iOS double-tap zoom exactly where double-tap means like */
.pmedia, .pact { touch-action: manipulation; }

/* --- the heart bloom (double-tap) --- */
.bloom {
  position: absolute; width: 96px; height: 96px; pointer-events: none;
  transform: translate(-50%, -50%); z-index: 3;
}
.bloom svg { width: 100%; height: 100%; fill: none;
             stroke: var(--ember); stroke-width: 1.4;
             stroke-linecap: round; stroke-linejoin: round;
             filter: drop-shadow(0 4px 18px rgba(23, 23, 22, .3));
             animation: bloom .85s var(--e-out) both; }
.bloom svg .cf { fill: var(--ember); }
@keyframes bloom {
  0% { transform: scale(0); opacity: 0; }
  18% { transform: scale(1.18); opacity: 1; }
  36% { transform: scale(.96); }
  58% { transform: scale(1); opacity: 1; }
  100% { transform: scale(.4) translateY(-40px); opacity: 0; }
}

/* --- image choreography: shimmer under, decode-then-fade in. Cached
   images (tab returns, card rewrites) become ready with no animation,
   so nothing ever re-flashes. --- */
.pmedia { position: relative; }
.pmedia::before {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(100deg, var(--cream) 40%,
    #efe9dc 50%, var(--cream) 60%);
  background-size: 220% 100%;
  animation: shimmer 1.8s linear infinite;
}
.pmedia:has(img.ready)::before { animation: none; content: none; }
.pmedia img { position: relative; }
img.ld { opacity: 0; }
img.ld.ready { opacity: 1; transition: opacity var(--d-travel) var(--e-out); }
img.noanim { transition: none !important; }
@keyframes shimmer { to { background-position: -120% 0; } }

/* --- skeletons: the stage held at final geometry --- */
.skb { display: block; border-radius: 8px;
       background: linear-gradient(100deg, #eee8db 40%, #f6f1e6 50%,
         #eee8db 60%);
       background-size: 220% 100%;
       animation: shimmer 1.8s linear infinite; }
.skel .skav { width: 38px; height: 38px; border-radius: 50%; flex: none; }
.skel .skl1 { width: 40%; height: 12px; margin-bottom: 7px; }
.skel .skl2 { width: 24%; height: 9px; }
.skel .skimg { aspect-ratio: 1 / .8; border-radius: 0; }
.skel .skl3 { width: 86%; height: 12px; margin: 12px 0 8px; }
.skel .skl4 { width: 55%; height: 12px; margin-bottom: 14px; }
.skring { width: 62px; height: 62px; border-radius: 50%; }

/* --- the paper's first entrance, once a day, eight cards at most --- */
.post.enter1 { animation: rise1 .5s var(--e-out) both;
               animation-delay: calc(var(--i) * 55ms); }
@keyframes rise1 {
  from { opacity: 0; transform: translateY(12px); }
}

/* --- pull-to-refresh ---
   FIXED to the top of the viewport. It used to be a static block at the
   end of <body>, which grew below the whole document where no thumb
   could ever see it (2026-08-23). `.pull` is on while a finger is down:
   the height must track the finger exactly, and an easing curve on a
   dragged value is lag, not polish. */
.ptr { position: fixed; left: 0; right: 0; z-index: 39;
       /* Under the chrome (z 40, sticky, its own height plus the notch),
          so the spinner is revealed in the space the pull opens rather
          than landing on top of the wordmark. */
       top: calc(max(10px, env(safe-area-inset-top, 0px)) + 42px);
       height: 0; overflow: hidden; display: grid; place-items: center;
       pointer-events: none;
       transition: height var(--d-enter) var(--e-out); }
.ptr.pull { transition: none; }
/* The page rides the pull and settles back on release. The transform is
   inline and lives only while the finger is down. */
.wrap.ptrsettle { transition: transform var(--d-enter) var(--e-out); }
.ptrspin { width: 26px; height: 26px; border-radius: 50%;
           border: 2.5px solid var(--line);
           border-top-color: var(--accent);
           opacity: .4; transform: rotate(40deg);
           transition: opacity var(--d-tap) var(--e-out),
                       transform var(--d-tap) var(--e-out); }
.ptr.go .ptrspin { opacity: 1; transform: rotate(220deg); }
.ptr.spin .ptrspin { opacity: 1; animation: ptrspin .8s linear infinite; }
@keyframes ptrspin { to { transform: rotate(400deg); } }

/* --- comments, threaded --- */
.crow2 { display: flex; align-items: flex-start; gap: 11px;
         padding: 11px 0; }
.crow2 .av { flex: none; }
.crow2 .cmain { flex: 1; min-width: 0; }
.crow2 .cbd { font-size: 14.5px; line-height: 1.45;
              overflow-wrap: anywhere; }
.crow2 .cbd b { font-weight: 600; }
.crow2.creplyrow { padding-left: 44px; }
.cmeta { display: flex; align-items: baseline; gap: 14px; margin-top: 5px;
         font-size: 12.5px; color: var(--muted); }
.cmeta .creply, .cmeta .cdel2 { background: none; border: 0; padding: 0;
                                font-size: 12.5px; font-weight: 600;
                                color: var(--muted); }
.cmeta .cdel2 { font-weight: 400; }
.chrt { background: none; border: 0; padding: 6px 0 6px 8px;
        line-height: 0; flex: none; align-self: flex-start;
        transition: transform var(--d-tap) var(--e-out); }
.chrt:active { transform: scale(var(--press-ico)); }
.chrt svg { width: 15px; height: 15px; fill: none; stroke: var(--muted);
            stroke-width: 1.7; stroke-linecap: round;
            stroke-linejoin: round; }
.chrt.on svg { stroke: var(--ember); }
.chrt.on svg .cf { fill: var(--ember); }
.chrt.pop svg { animation: heartpop .34s var(--e-pop); }
.cviewrep { display: flex; align-items: center; gap: 8px;
            background: none; border: 0; padding: 2px 0 8px 49px;
            font-size: 12.5px; font-weight: 600; color: var(--muted); }
.cviewrep i { width: 26px; height: 1px; background: var(--line);
              display: inline-block; }
.creplying[hidden] { display: none; }   /* author flex beats [hidden] */
.creplying { display: flex; align-items: center; gap: 8px;
             background: var(--ground); border-radius: 10px;
             padding: 8px 12px; margin-bottom: 8px; font-size: 13px;
             color: var(--ink-2); }
.creplying span { flex: 1; }
.crepx { background: none; border: 0; font-size: 17px;
         color: var(--muted); padding: 0 2px; }
/* 16px floor: below that, iOS zooms the page on focus */
.field textarea, .field input { font-size: 16px; }

/* --- reduced motion: the craft layer stands still --- */
@media (prefers-reduced-motion: reduce) {
  .pmedia::before, .skb { animation: none; }
  .post.enter1 { animation: none; }
  .bloom svg { animation-duration: .01s; }
  img.ld.ready { transition: none; }
}


/* the consent ceremony's bystander rule */
.consent-by { display: flex; gap: 10px; align-items: flex-start;
              background: var(--ground); border: 1px solid var(--line);
              border-radius: 12px; padding: 11px 13px; margin: 0 0 14px;
              font-size: 12.5px; color: var(--ink-2); line-height: 1.5;
              text-align: left; }
.consent-by input { width: 17px; height: 17px; margin-top: 1px;
                    flex: none; accent-color: var(--good); }

/* the post menu */
.pmrows { display: grid; }
.pmrow {
  background: none; border: 0; border-bottom: 1px solid var(--line-soft);
  padding: 15px 2px; font-size: 15.5px; text-align: left; color: var(--ink);
}
.pmrow:last-child { border-bottom: 0; }
.pmrow.danger { color: #a3382a; }


/* notification prefs rows: label + a drawn switch, no native controls */
.pmrow.prefrow { display: flex; align-items: center; gap: 12px; }
.pmrow.prefrow > span { flex: 1; min-width: 0; }
.pmrow.prefrow b { display: block; font-size: 15px; }
.pmrow.prefrow small { display: block; font-size: 12.5px;
                       color: var(--muted); margin-top: 2px;
                       line-height: 1.4; }
.sw { width: 44px; height: 26px; border-radius: 999px; flex: none;
      background: var(--line); position: relative; display: inline-block;
      transition: background var(--d-tap) var(--e-out); font-style: normal; }
.sw::after { content: ""; position: absolute; top: 3px; left: 3px;
             width: 20px; height: 20px; border-radius: 50%;
             background: var(--paper); box-shadow: var(--shadow);
             transition: transform var(--d-tap) var(--e-out); }
.sw.on { background: var(--good); }
.sw.on::after { transform: translateX(18px); }


/* the wall a stranger meets behind a forwarded link */
.vwall-wrap { display: grid; place-items: center; min-height: 76dvh; }
.vwall { text-align: center; padding: 34px 22px 26px; width: 100%;
         background: var(--paper); border: 1px solid var(--line);
         border-radius: var(--r-lg); box-shadow: var(--shadow); }
.vwall .jm { width: 52px; height: auto; margin-bottom: 14px; }
.vwall .jm path { fill: var(--ink); }
.vwall h2 { font-family: var(--serif); font-weight: 400; font-size: 24px;
            margin: 0 0 8px; letter-spacing: 0; text-transform: none;
            color: var(--ink); }
.vwall p { color: var(--muted); font-size: 14.5px; line-height: 1.55;
           margin: 0 0 18px; }

/* the photo, full screen */
.pview {
  position: fixed; inset: 0; z-index: 90; display: grid; place-items: center;
  /* Solid, not a 94% scrim: at any transparency the tab bar and the
     header ghost through behind the photo and the viewer reads as a
     dimmed screen rather than a picture. */
  background: var(--night); opacity: 0; transition: opacity var(--d-enter) var(--e-out);
  padding: env(safe-area-inset-top, 12px) 12px env(safe-area-inset-bottom, 12px);
}
.pview.in { opacity: 1; }
.pview img { max-width: 100%; max-height: 100%; object-fit: contain;
             border-radius: 8px; }

.uprow { display: flex; align-items: center; gap: 10px; }
.uprow .btn { margin-left: auto; }
.upnote { color: var(--muted); font-size: 13.5px; margin-top: 10px; }
.fgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
         margin-bottom: 12px; }
.fcard { background: var(--paper); border: 1px solid var(--line);
         border-radius: var(--r-md); overflow: hidden;
         box-shadow: var(--shadow); }
.fim { aspect-ratio: 1 / 1; }
.fim img { width: 100%; height: 100%; object-fit: cover; display: block; }
.fim.fmono { display: grid; place-items: center; background: var(--cream);
             font-family: var(--serif); font-size: 40px;
             color: var(--ink-2); }
.fbd { padding: 10px 12px 12px; }
.fbd .nm { font-size: 15px; font-weight: 500; }
.fwhy { font-size: 12.5px; color: var(--muted); margin-top: 2px;
        line-height: 1.35; min-height: 34px; }
.fft { display: flex; align-items: center; justify-content: space-between;
       gap: 6px; margin-top: 8px; }
.fft .intent { white-space: nowrap; overflow: hidden;
               text-overflow: ellipsis; }
.fft .btn.sm { white-space: nowrap; padding: 6px 11px; font-size: 13px; }

/* --------------------------------------------- booking, in the app */
/* The whole flow is one sheet: browse, when, review, pay, done. Money
   figures are always rendered from the server's quote. */
.bkhd { display: flex; align-items: center; gap: 10px; margin: -2px 0 12px; }
.bkhd .bkback { width: 30px; height: 30px; border-radius: 50%; flex: none;
                background: var(--ground); border: 1px solid var(--line);
                display: grid; place-items: center; font-size: 17px;
                color: var(--ink-2); padding: 0; }
.bkhd h3 { font-family: var(--serif); font-weight: 400; font-size: 20px;
           margin: 0; flex: 1; min-width: 0; }
.bkgrp { margin: 18px 0 8px; display: flex; align-items: baseline; gap: 8px; }
.bkgrp b { font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
           color: var(--muted); font-weight: 600; }
.bkgrp span { margin-left: auto; font-size: 12px; color: var(--muted); }
.bkroom { display: flex; gap: 11px; align-items: center; width: 100%;
          text-align: left; background: var(--paper);
          border: 1px solid var(--line); border-radius: var(--r-md);
          padding: 8px; box-shadow: var(--shadow); margin-bottom: 8px; }
.bkroom img { width: 78px; height: 58px; border-radius: 9px; flex: none;
              object-fit: cover; background: var(--cream); }
.bkroom .bkrb { flex: 1; min-width: 0; }
.bkroom .bkrn { display: block; font-size: 14.5px; font-weight: 500;
                line-height: 1.25; }
.bkroom .bkrm { display: block; font-size: 12px; color: var(--muted);
                margin-top: 2px; }
.bkroom .bkrp { text-align: right; flex: none; }
.bkroom .bkrp b { font-size: 14.5px; font-weight: 600;
                  font-variant-numeric: tabular-nums; }
.bkroom .bkrp small { display: block; font-size: 10.5px; color: var(--muted); }
.bkfree { display: inline-block; font-size: 10px; font-weight: 700;
          letter-spacing: .05em; color: #245c44; background: #e7f2ec;
          border: 1px solid #cfe6da; border-radius: 999px; padding: 2px 7px;
          margin-top: 4px; }
/* Five durations at phone width wrapped 3-then-2 and centred, which reads
   as a ragged accident rather than a row of choices. The pills stretch to
   fill whatever row they land on instead, so both rows run edge to edge
   under the day chips. A modifier, not a change to .choices: that class
   is centred on purpose everywhere else in the app. */
.choices.bkdurs { display: grid; grid-template-columns: repeat(6, 1fr); }
.choices.bkdurs .choice { grid-column: span 2; padding-left: 6px;
                          padding-right: 6px; white-space: nowrap; }
/* A room offers either five durations or two (bkDurations). Five: three
   across, then the last pair splits the second row in half. Two: half
   each. Any other count falls back to three across, which is why the
   rules are keyed to position from BOTH ends rather than hard-coded. */
.choices.bkdurs .choice:nth-child(4):nth-last-child(2),
.choices.bkdurs .choice:nth-child(4):nth-last-child(2) ~ .choice,
.choices.bkdurs .choice:first-child:nth-last-child(2),
.choices.bkdurs .choice:first-child:nth-last-child(2) ~ .choice {
  grid-column: span 3;
}
.bkdays { display: flex; gap: 6px; margin-bottom: 14px; }
.bkday { flex: 1; text-align: center; border: 1px solid var(--line);
         background: var(--paper); border-radius: 11px; padding: 7px 0 6px; }
/* Both spans are display:block on purpose: the chip is a weekday STACKED
   over a date. Left inline they ran together as "FRI21" and the .dn
   margin-top did nothing, because margin-top is inert on an inline box. */
.bkday .dw { display: block; font-size: 10px; color: var(--muted);
             text-transform: uppercase; letter-spacing: .05em;
             line-height: 1.2; }
.bkday .dn { display: block; font-size: 15px; font-weight: 500;
             margin-top: 1px; line-height: 1.2; }
.bkday.on { background: var(--ink); border-color: var(--ink);
            color: var(--cream); }
.bkday.on .dw { color: rgba(244,240,231,.72); }
.bkslots { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
.bkslot { border: 1px solid var(--line); background: var(--paper);
          border-radius: 9px; padding: 9px 0; text-align: center;
          font-size: 12.5px; font-variant-numeric: tabular-nums; }
.bkslot.on { background: var(--ink); border-color: var(--ink);
             color: var(--cream); }
.bkband { display: block; width: 100%; text-align: left;
          border: 1px solid var(--line); background: var(--paper);
          border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 8px;
          box-shadow: var(--shadow); }
.bkband.on { border-color: var(--ink); box-shadow: 0 0 0 1.5px var(--ink); }
.bkband b { font-size: 14.5px; font-weight: 500; }
.bkband small { display: block; font-size: 12px; color: var(--muted);
                margin-top: 2px; }
.bkband i { float: right; font-style: normal; font-weight: 600;
            font-variant-numeric: tabular-nums; }
.bkcov { background: #e7f2ec; border: 1px solid #cfe6da;
         border-radius: var(--r-md); padding: 9px 12px; font-size: 12.5px;
         color: #245c44; margin-bottom: 12px; }
.bkled { font-variant-numeric: tabular-nums; }
.bkled .r { display: flex; justify-content: space-between;
            align-items: baseline; padding: 7px 0; font-size: 14px; }
.bkled .r + .r { border-top: 1px solid var(--line-soft); }
.bkled .r small { display: block; font-size: 11.5px; color: var(--muted);
                  margin-top: 1px; }
.bkled .r.good, .bkled .r.good span { color: var(--good); }
.bkled .tot { display: flex; justify-content: space-between;
              align-items: baseline; padding: 11px 0 2px;
              border-top: 1.5px solid var(--line); margin-top: 3px; }
.bkled .tot b { font-size: 14.5px; font-weight: 600; }
.bkled .tot i { font-family: var(--serif); font-style: normal;
                font-size: 25px; }
.bktog { display: flex; align-items: center; gap: 11px; padding: 10px 0 2px; }
.bktog + .bktog { border-top: 1px solid var(--line-soft); }
.bktog .tx { flex: 1; }
.bktog .tx b { display: block; font-size: 14px; font-weight: 500; }
.bktog .tx small { font-size: 11.5px; color: var(--muted); }
.bkheld { display: inline-flex; align-items: center; gap: 7px;
          font-size: 12px; color: var(--warn); background: #fdf4e8;
          border: 1px solid #f0dcbe; border-radius: 999px; padding: 5px 11px;
          margin-bottom: 11px; }
.bksumm { display: flex; gap: 11px; align-items: center; }
.bksumm img { width: 58px; height: 58px; border-radius: 11px; flex: none;
              object-fit: cover; background: var(--cream); }
/* .bsn/.bsw, not .sn/.sw: `.sw` is the prefs switch above and it won
   the cascade here, turning the booking date into a 44px grey pill with a
   knob on it. Scoped names, and the text column is a real flex child. */
.bksumm > div { flex: 1; min-width: 0; }
.bksumm .bsn { font-family: var(--serif); font-size: 17px;
               line-height: 1.25; }
.bksumm .bsw { font-size: 12.5px; color: var(--muted); margin-top: 2px;
               line-height: 1.4; }
.bkdone { text-align: center; padding: 8px 0 2px; }
.bktick { width: 58px; height: 58px; border-radius: 50%; background: #e7f2ec;
          border: 1px solid #cfe6da; display: grid; place-items: center;
          margin: 0 auto 13px; }
.bktick svg { width: 26px; height: 26px; fill: none; stroke: var(--good);
              stroke-width: 2.2; stroke-linecap: round;
              stroke-linejoin: round; }
.bkgone { background: #fdf4e8; border: 1px solid #f0dcbe;
          border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 14px; }
.bkgone b { display: block; font-family: var(--serif); font-weight: 400;
            font-size: 17px; margin-bottom: 3px; }
.bkgone span { font-size: 13px; color: var(--muted); line-height: 1.45; }
#bk-embed { margin: 10px 0 4px; min-height: 220px; }
.bkup { background: var(--paper); border: 1px solid var(--line);
        border-radius: var(--r-md); padding: 12px 14px; box-shadow: var(--shadow);
        margin-bottom: 9px; }
.bkup .uh { display: flex; align-items: baseline; gap: 8px; }
.bkup .un { font-size: 14.5px; font-weight: 500; margin-right: auto; }
.bkup .ud { font-size: 12px; color: var(--muted); }
.bkup .uw { font-size: 13px; margin-top: 3px; }
.bkup .up2 { font-size: 12px; color: var(--good); margin-top: 5px; }
.bkup .ur { display: flex; gap: 7px; margin-top: 10px; }
.bkup .ur .btn { flex: 1; }
/* GET A ROOM READY. Sits under the hero on Today whether or not anything
   is booked, because "you have no booking" was exactly the state in which
   there was nothing to tap. */
.prepcard { display: block; width: 100%; background: var(--paper);
            border: 1px solid var(--line); border-radius: var(--r-md);
            box-shadow: var(--shadow); margin-bottom: 14px;
            font: inherit; color: inherit; text-align: left; }
.prepcard:not(.prepcard--on) { display: flex; align-items: center; gap: 12px;
                               padding: 14px 16px; }
.prepcard--on { padding: 0; }
.pc-open { display: flex; align-items: center; gap: 12px; width: 100%;
           padding: 14px 16px; background: none; border: 0; font: inherit;
           color: inherit; text-align: left; }
.prepcard:active, .pc-open:active { transform: scale(var(--press-row)); }
.pc-ic { flex: none; width: 38px; height: 38px; border-radius: 50%;
         background: var(--line-soft, #efece4); color: var(--ink-2);
         display: grid; place-items: center; }
.pc-ic.on { background: var(--accent); color: var(--accent-ink); }
.pc-ic .jpi { width: 19px; height: 19px; }
.pc-t { flex: 1; min-width: 0; }
.pc-t b { display: block; font-size: 14.5px; font-weight: 600;
          line-height: 1.35; }
.pc-t small { display: block; margin-top: 2px; font-size: 12.5px;
              color: var(--muted); line-height: 1.45; }
.prepcard .jpi { flex: none; }
.prepcard > .jpi, .pc-open > .jpi { width: 16px; height: 16px; opacity: .45;
                                    stroke: currentColor; stroke-width: 2;
                                    stroke-linecap: round;
                                    stroke-linejoin: round; }
/* THE SELECTOR HAS TO BEAT .btn.wide. This button carries
   `btn gold wide pc-go`, and `.btn.wide { width: 100% }` is two classes
   to `.pc-go`'s one, so the inset width lost and the gold button ran
   16px past the card's own right edge (Fahad, 2026-08-25). Three classes
   here, deliberately, and never write this rule as `.pc-go` again. */
.btn.wide.pc-go { margin: 0 16px 16px; width: calc(100% - 32px); }

/* The row opens the booking; the strip under it prepares the room. Two
   controls, so the card is a div and .bkopen carries what the card used
   to do itself. */
.bkopen { display: block; width: 100%; text-align: left; background: none;
          border: 0; padding: 0; font: inherit; color: inherit; }
.bkprep { display: flex; align-items: center; gap: 9px; width: 100%;
          margin-top: 11px; padding-top: 10px;
          border: 0; border-top: 1px solid var(--line-soft, #efece4);
          background: none; font: inherit; font-size: 12.5px;
          color: var(--muted); text-align: left; }
.bkprep > span { flex: 1; min-width: 0; }
.bkprep .jpi { width: 15px; height: 15px; flex: none; opacity: .5;
               stroke: currentColor; stroke-width: 2; stroke-linecap: round;
               stroke-linejoin: round; }
.bkprep::before { content: ""; flex: none; width: 6px; height: 6px;
                  border-radius: 999px; background: transparent;
                  border: 1.5px solid #cdc9bd; }
.bkprep.on { color: var(--ink-2); }
.bkprep.on::before { background: var(--accent); border-color: var(--accent); }

/* ---------------------------------------------- support (Get help, R1)
   The picker reuses .frow, so a choice looks like every other row in the
   app; only the selected mark, the small headings and the thread are new. */
.sect2 { font-size: 11px; letter-spacing: .1em; text-transform: uppercase;
         color: var(--muted); font-weight: 700; margin: 16px 2px 8px; }
.tkdot { width: 19px; height: 19px; border-radius: 50%; flex: none;
         border: 1.6px solid #d5d2c8; }
.tkdot.on { border-color: var(--accent); background: var(--accent);
            box-shadow: inset 0 0 0 3.6px var(--paper); }
.sheet textarea { width: 100%; box-sizing: border-box; resize: vertical;
                  border: 1px solid var(--line); border-radius: var(--r-md);
                  padding: 11px 13px; font: inherit; font-size: 15px;
                  background: var(--paper); color: var(--ink); }
.sheet textarea:focus { outline: none; border-color: var(--accent); }
.tkthread { display: flex; flex-direction: column; gap: 9px;
            margin: 4px 0 14px; }
.tkb2 { max-width: 86%; padding: 10px 13px; border-radius: 15px;
        font-size: 14px; line-height: 1.45; white-space: pre-wrap;
        word-break: break-word; }
.tkb2.them { align-self: flex-start; background: var(--paper);
             border: 1px solid var(--line); border-bottom-left-radius: 5px; }
.tkb2.me { align-self: flex-end; background: var(--night); color: #f2efe6;
           border-bottom-right-radius: 5px; }
.tkb2 small { display: block; font-size: 11px; margin-top: 4px;
              color: var(--muted); }
.tkb2.me small { color: #a9a79f; }

/* Wide screens: a 4:5 card at wrap width is a poster, so it keeps its
   phone proportions and sits centred; the board goes three up. Lives
   AFTER the base rules on purpose: media queries add no specificity,
   so source order is the tiebreak. */
@media (min-width: 900px) {
  .pcard { max-width: 430px; margin-left: auto; margin-right: auto; }
  .pcfine { max-width: 430px; margin-left: auto; margin-right: auto; }
  .fgrid { grid-template-columns: 1fr 1fr 1fr; }
}

/* ---- the room wall, previewed (2026-08-19) --------------------------
   A picture of the actual board, in the WALL's colours rather than the
   app's: cream and the serif. It is not a component of this app's
   surface, it is a thumbnail of a room, and dressing it as a card would
   quietly lie about what the customer's guests will see. */
.prwall { position: relative; margin: 2px 0 4px; padding: 5% 6%;
          border: 1px solid var(--line); border-radius: 14px;
          background: var(--cream); aspect-ratio: 16 / 9;
          display: flex; flex-direction: column; justify-content: center;
          overflow: hidden; }
.prwall .pwtop { position: absolute; top: 6%; right: 5%;
                 font-family: var(--serif);
                 font-size: clamp(8px, 2.2vw, 12px); color: var(--ink); }
.prwall .pwrule { width: 9%; height: 3px; border-radius: 2px;
                  background: var(--accent); margin-bottom: 4%; }
.prwall .pwlogo { display: block; max-height: 26%; max-width: 52%;
                  object-fit: contain; object-position: left bottom;
                  margin-bottom: 3%; }
.prwall .pwhero { font-family: var(--serif);
                  font-size: clamp(15px, 5.4vw, 30px); line-height: 1.1;
                  color: var(--ink); overflow: hidden;
                  text-overflow: ellipsis; white-space: nowrap; }
.prwall .pwsub { font-size: clamp(8px, 2.4vw, 13px); color: var(--ink-2);
                 margin-top: 2%; }

/* the character count sits on the label's own line, right-aligned */
.field label .prcount { float: right; font-variant-numeric: tabular-nums;
                        color: var(--muted); }
.prkeep { display: flex; gap: 9px; align-items: center; font-size: 13.5px;
          color: var(--ink-2); margin: -4px 2px 12px; }
.prkeep input { width: 17px; height: 17px; accent-color: var(--ink); }

/* ---- what the room is for, and the discretion switch (2026-08-19) ---- */
.prchips { display: flex; flex-wrap: wrap; gap: 8px; }
.prchip { border: 1px solid var(--line); border-radius: 999px; padding: 9px 15px;
          font: inherit; font-size: 14px; color: var(--ink-2);
          background: var(--ground); transition: transform var(--d-tap) var(--e-out); }
.prchip:active { transform: scale(var(--press-btn)); }
.prchip.on { background: var(--ink); color: var(--paper); border-color: var(--ink); }

.prdisc { display: flex; gap: 12px; align-items: flex-start;
          border-top: 1px solid var(--line); padding-top: 16px; margin-top: 4px; }
.prdisc-t { flex: 1; min-width: 0; }
.prdisc-t b { display: block; font-size: 15px; margin-bottom: 3px; }
.prdisc-t span { font-size: 13px; line-height: 1.5; color: var(--muted); }
.prsw { width: 46px; height: 28px; border-radius: 999px; background: #d8d4c8;
        flex: none; position: relative; border: 0; padding: 0; margin-top: 2px;
        transition: background var(--d-tap) var(--e-out); }
.prsw::after { content: ""; position: absolute; top: 3px; left: 3px;
               width: 22px; height: 22px; border-radius: 50%; background: #fff;
               box-shadow: 0 1px 3px rgba(0,0,0,.25); transition: left var(--d-tap) var(--e-out); }
.prsw.on { background: var(--ink); }
.prsw.on::after { left: 21px; }
/* Interviews holds it on; it reads as settled, not as broken */
.prsw.locked { opacity: .6; }

.prnote { border-left: 2px solid var(--accent); padding: 2px 0 2px 12px;
          margin: 12px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-2); }
.prnote b { font-weight: 600; }

/* ==================================================== design R3 (2026-08-19)
   The inhabited floor: the masthead, green presence, the Everyone
   directory, Boost, and the Lightbox. */

/* ---- the masthead: the paper finally looks like an edition ---- */
.mast { padding-top: 6px; }
.mastrow { display: flex; align-items: center; gap: 9px; }
.mast .mast-j { width: 14px; height: 21px; flex: none; }
.mast .mast-j path { fill: var(--ink); }
.masteyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
               text-transform: uppercase; color: var(--muted); flex: 1; }
.mastrow .vbell { margin-left: auto; }
.mastdate { font-family: var(--serif); font-weight: 400; font-size: 30px;
            letter-spacing: -.4px; line-height: 1.12; margin: 9px 0 0; }
.mastmeta { font-size: 13px; color: var(--muted); margin-top: 5px; }
.mastrule { border-top: 2.5px solid var(--ink); margin-top: 13px;
            position: relative; }
.mastrule::after { content: ""; position: absolute; left: 0; right: 0;
                   top: 2px; border-top: 1px solid var(--ink); }
.mast + .vstrip { margin-top: 16px; }

/* ---- green: on the floor, by their own tap ---- */
.avw { position: relative; display: inline-block; line-height: 0;
       flex: none; }
.vdot { position: absolute; right: 2px; bottom: 2px; width: 15px;
        height: 15px; border-radius: 50%; background: var(--good);
        border: 2.5px solid var(--ground); pointer-events: none; }
.vface .vyou.green svg { stroke: var(--good); }
.gdot { width: 15px; height: 15px; border-radius: 50%; flex: none;
        background: var(--good); }
.grow { display: flex; align-items: center; gap: 12px; }
.grow b { font-size: 15.5px; }
.grow > b { flex: 1; }
.grow.top { align-items: flex-start; }
.grow.top .gdot { margin-top: 3px; }
.grow.btns { margin-top: 14px; gap: 10px; }
.grow.btns .btn { flex: none; white-space: nowrap; }

/* ---- the Everyone directory ---- */
.dsearch { display: flex; align-items: center; gap: 10px;
           background: var(--paper); border: 1px solid var(--line);
           border-radius: 999px; padding: 2px 16px;
           box-shadow: var(--shadow); margin: 2px 0 12px; }
.dsearch svg { width: 18px; height: 18px; fill: none;
               stroke: var(--muted); stroke-width: 1.8;
               stroke-linecap: round; flex: none; }
.dsearch input { flex: 1; border: 0; background: none; font: inherit;
                 font-size: 15px; padding: 11px 0; color: var(--ink);
                 outline: none; min-width: 0; }
.dsearch input::placeholder { color: var(--muted); }
.dcard { padding-top: 3px; padding-bottom: 3px; }
.drow { display: flex; align-items: center; gap: 12px; padding: 10px 0;
        border-bottom: 1px solid var(--line-soft); }
.drow:last-child { border-bottom: 0; }
.drow .avw, .drow .dbd { background: none; border: 0; padding: 0;
                         text-align: left; }
.drow .avw .vdot { width: 13px; height: 13px; right: -1px; bottom: -1px;
                   border-color: var(--paper); }
.drow .dbd { flex: 1; min-width: 0; }
.drow .nm { display: block; font-size: 15px; font-weight: 600;
            color: var(--ink); white-space: nowrap; overflow: hidden;
            text-overflow: ellipsis; }
.drow .dsub { display: block; font-size: 13px; color: var(--muted);
              margin-top: 2px; white-space: nowrap; overflow: hidden;
              text-overflow: ellipsis; }
.drow .vfollow { align-self: center; }
.mk-unlist { font-size: 12.5px; color: var(--muted); line-height: 1.5;
             margin: 10px 2px 0; }

/* ---- Posts | Boosts, the page shelves ---- */
.shelfseg { display: inline-flex; border: 1px solid var(--line);
            border-radius: 999px; overflow: hidden;
            background: var(--paper); margin: 2px 0 12px; }
.shelfseg button { border: 0; background: none; padding: 8px 18px;
                   font-size: 13.5px; color: var(--muted); }
.shelfseg button.on { background: var(--ink); color: var(--cream);
                      font-weight: 600; }
.aic.lift svg { stroke: var(--warn); }

/* ---- the Lightbox: the app's one dark room ---- */
.lbox { position: fixed; inset: 0; z-index: 55; background: var(--night);
        opacity: 0; transition: opacity var(--d-tap) var(--e-out),
                                transform var(--d-tap) var(--e-out); }
.lbox.in { opacity: 1; }
.lb-track { display: flex; height: 100%; overflow-x: auto;
            overflow-y: hidden; scroll-snap-type: x mandatory;
            scrollbar-width: none; touch-action: pan-x;
            overscroll-behavior-x: contain; }
.lb-track::-webkit-scrollbar { display: none; }
.lb-slide { flex: 0 0 100%; width: 100%; min-width: 0;
            scroll-snap-align: center; scroll-snap-stop: always;
            display: flex; flex-direction: column;
            padding: max(14px, env(safe-area-inset-top, 14px)) 0
                     max(12px, env(safe-area-inset-bottom, 12px)); }
.lb-top { display: flex; align-items: center; gap: 10px;
          padding: 2px 12px 10px; transition: opacity var(--d-tap) var(--e-out); }
.lb-top button { background: none; border: 0; padding: 6px;
                 line-height: 0; color: #fff; }
.lb-top svg { width: 22px; height: 22px; fill: none; stroke: #fff;
              stroke-width: 1.8; stroke-linecap: round;
              stroke-linejoin: round; }
/* .lb-top button zeroes line-height for icon centring and outranks
   .lb-who, so the text button takes its line boxes back per element,
   or the name collapses to a 0-height strip that overflow then clips. */
.lb-who { flex: 1; min-width: 0; text-align: left; }
.lb-who b { display: block; font-size: 14.5px; line-height: 1.25;
            color: #fff; white-space: nowrap; overflow: hidden;
            text-overflow: ellipsis; }
.lb-who span { display: block; font-size: 10.5px; line-height: 1.25;
               letter-spacing: .09em; text-transform: uppercase;
               color: rgba(255,255,255,.55); margin-top: 2px; }
.lb-mid { flex: 1; min-height: 0; display: grid; place-items: center;
          position: relative; overflow: hidden; }
.lb-mid img { max-width: 100%; max-height: 100%; object-fit: contain;
              will-change: transform; }
.lb-txt { background: var(--cream); border-radius: var(--r-lg);
          margin: 0 26px; padding: 30px 24px; max-width: 420px; }
.lb-txt .tk { font-size: 10.5px; font-weight: 700; letter-spacing: .12em;
              text-transform: uppercase; color: var(--muted); }
.lb-txt p { font-family: var(--serif); font-size: 21px; line-height: 1.42;
            color: var(--ink); margin: 10px 0 0;
            overflow-wrap: break-word; }
.lb-foot { padding: 10px 14px 0; transition: opacity var(--d-tap) var(--e-out); }
.lb-cap { color: rgba(255,255,255,.88); font-size: 14.5px;
          line-height: 1.5; display: -webkit-box; -webkit-line-clamp: 2;
          -webkit-box-orient: vertical; overflow: hidden; }
.lb-cap b { color: #fff; }
.lb-act { display: flex; align-items: center; padding-top: 8px; }
.lb-act button { background: none; border: 0; padding: 9px 5px 9px 9px;
                 line-height: 0; position: relative; }
.lb-act svg { width: 24px; height: 24px; fill: none; stroke: #fff;
              stroke-width: 1.65; stroke-linecap: round;
              stroke-linejoin: round; }
.lb-act .plike.on svg { stroke: var(--ember); }
.lb-act .plike.on svg .cf { fill: var(--ember); }
.lb-act .pboost.on svg { stroke: var(--accent); }
.lb-n { color: rgba(255,255,255,.85); font-size: 13px; margin-right: 6px;
        min-width: 10px; font-variant-numeric: tabular-nums; }
.lb-fwd { margin-left: auto; }
.lbox.min .lb-top, .lbox.min .lb-foot { opacity: 0; pointer-events: none; }

@media (prefers-reduced-motion: reduce) {
  .lbox { transition: none; }
  .pact .plike.pop .flk.f1, .pact .plike.pop .flk.f2,
  .pact .plike.pop .flk.f3 { animation: none; }
  .pact button.pop svg { animation: none; }
}

/* ------------------------------------------------------------- clips
   (design R4) The card wears a play badge and its length; the room is
   the app's second dark surface, vertical where the Lightbox is
   horizontal, because a clip's grammar is swipe-up. Ember stays the
   cup's colour and nothing else. */
.pclip { position: relative; }
.pclip.nocov { background: var(--night); }
.pplay { position: absolute; left: 50%; top: 50%; z-index: 2;
         transform: translate(-50%, -50%); width: 56px; height: 56px;
         border-radius: 50%; background: rgba(16,24,22,.45);
         backdrop-filter: blur(5px); -webkit-backdrop-filter: blur(5px);
         display: grid; place-items: center; pointer-events: none; }
.pplay i { display: block; width: 0; height: 0; margin-left: 4px;
           border-style: solid; border-width: 11px 0 11px 18px;
           border-color: transparent transparent transparent
             var(--cream); }
.pdur { position: absolute; right: 10px; bottom: 10px; z-index: 2;
        color: #fff; background: rgba(16,24,22,.55);
        border-radius: 999px; padding: 3px 9px; font-size: 11.5px;
        font-variant-numeric: tabular-nums; pointer-events: none; }

/* the author-only states */
.pdev { display: flex; gap: 12px; align-items: center;
        margin: 0 14px 4px; padding: 12px 13px;
        background: var(--ground); border: 1px solid var(--line);
        border-radius: var(--r-md); }
.pdev .pdevcov { position: relative; width: 52px; height: 68px;
                 flex: none; border-radius: 9px; display: grid;
                 place-items: center;
                 background: linear-gradient(110deg,
                   var(--line-soft) 32%, #f9f7f1 44%,
                   var(--line-soft) 56%);
                 background-size: 220% 100%;
                 animation: devshimmer 1.6s linear infinite; }
.pdev .pdevcov svg { width: 22px; height: 22px; fill: none;
                     stroke: var(--muted); stroke-width: 1.6;
                     stroke-linecap: round; }
.pdev > span:last-child { font-size: 12.5px; color: var(--muted);
                          line-height: 1.5; }
.pdev b { display: block; color: var(--ink); font-size: 13.5px; }
.pdev.pfail .pdevcov { animation: none; background: var(--line-soft); }
.pdev.pfail .pdevcov svg { stroke: var(--warn); }
@keyframes devshimmer { to { background-position: -120% 0; } }

/* the rail */
.crail-lbl { display: flex; align-items: baseline; gap: 8px;
             margin: 16px 2px 10px; }
.crail-lbl span { font-size: 10.5px; font-weight: 700;
                  letter-spacing: .14em; text-transform: uppercase;
                  color: var(--ink-2); }
.crail-lbl small { font-size: 12px; color: var(--muted); }
.crail { display: flex; gap: 10px; overflow-x: auto;
         padding-bottom: 4px; scrollbar-width: none;
         margin: 0 -2px 4px; }
.crail::-webkit-scrollbar { display: none; }
.crail-t { position: relative; flex: none; width: 96px; height: 150px;
           border-radius: 14px; overflow: hidden; border: 0; padding: 0;
           background: var(--night); cursor: pointer;
           box-shadow: var(--shadow); }
.crail-t img { width: 100%; height: 100%; object-fit: cover;
               display: block; }
.crail-t::after { content: ""; position: absolute; inset: 0;
                  background: linear-gradient(180deg,
                    rgba(0,0,0,0) 55%, rgba(0,0,0,.42)); }
.crail-p { position: absolute; left: 50%; top: 50%; z-index: 2;
           transform: translate(-50%, -50%); width: 30px; height: 30px;
           border-radius: 50%; background: rgba(16,24,22,.5);
           backdrop-filter: blur(4px);
           -webkit-backdrop-filter: blur(4px);
           display: grid; place-items: center; }
.crail-p i { display: block; width: 0; height: 0; margin-left: 2px;
             border-style: solid; border-width: 6px 0 6px 10px;
             border-color: transparent transparent transparent
               var(--cream); }
.crail-d { position: absolute; top: 6px; right: 6px; z-index: 2;
           font-size: 9.5px; color: #fff;
           background: rgba(16,24,22,.55); border-radius: 999px;
           padding: 2px 6px; font-variant-numeric: tabular-nums; }
.crail-n { position: absolute; left: 8px; right: 8px; bottom: 6px;
           z-index: 2; color: #fff; font-size: 10.5px;
           font-weight: 600; text-align: left; white-space: nowrap;
           overflow: hidden; text-overflow: ellipsis; }

/* page-grid badges */
.ptile { position: relative; }
.tplay { position: absolute; top: 7px; right: 7px; z-index: 2;
         width: 22px; height: 22px; border-radius: 50%;
         background: rgba(16,24,22,.5); backdrop-filter: blur(3px);
         -webkit-backdrop-filter: blur(3px); display: grid;
         place-items: center; pointer-events: none; }
.tplay i { display: block; width: 0; height: 0; margin-left: 2px;
           border-style: solid; border-width: 4.5px 0 4.5px 7.5px;
           border-color: transparent transparent transparent
             var(--cream); }
.ptile.tdev { display: grid; place-items: center; gap: 6px;
              background: var(--ground); border: 1px dashed var(--line);
              color: var(--muted); }
.ptile.tdev svg { width: 22px; height: 22px; fill: none;
                  stroke: var(--muted); stroke-width: 1.6;
                  stroke-linecap: round; }
.ptile.tdev i { font-style: normal; font-size: 11px; }

/* the Clip Room */
.crbox { position: fixed; inset: 0; z-index: 55; background: var(--night);
         opacity: 0; transition: opacity var(--d-tap) var(--e-out); }
.crbox.in { opacity: 1; }
.cr-track { height: 100%; overflow-y: auto; scroll-snap-type: y mandatory;
            overscroll-behavior: contain; }
.cr-track::-webkit-scrollbar { display: none; }
.cr-slide { position: relative; height: 100%; width: 100%;
            scroll-snap-align: start; scroll-snap-stop: always;
            overflow: hidden; background: var(--night); }
.cr-slide video, .cr-slide .cr-cov {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: contain; background: var(--night); }
.cr-slide .cr-cov { object-fit: cover; }
.cr-top { position: absolute; left: 0; right: 0; top: 0; height: 120px;
          background: linear-gradient(180deg, rgba(0,0,0,.5),
            rgba(0,0,0,0)); pointer-events: none; }
.cr-bot { position: absolute; left: 0; right: 0; bottom: 0;
          height: 220px;
          background: linear-gradient(0deg, rgba(0,0,0,.62),
            rgba(0,0,0,0)); pointer-events: none; }
.cr-x { position: absolute; left: 10px;
        top: calc(env(safe-area-inset-top, 0px) + 10px); z-index: 6;
        background: none; border: 0; padding: 8px; cursor: pointer; }
.cr-x svg { width: 24px; height: 24px; fill: none; stroke: #fff;
            stroke-width: 1.8; stroke-linecap: round; display: block; }
.cr-snd { position: absolute; right: 12px;
          top: calc(env(safe-area-inset-top, 0px) + 10px); z-index: 6;
          width: 38px; height: 38px; border-radius: 50%; border: 0;
          background: rgba(255,255,255,.16); backdrop-filter: blur(6px);
          -webkit-backdrop-filter: blur(6px); display: grid;
          place-items: center; cursor: pointer; }
.cr-snd svg { width: 20px; height: 20px; fill: none; stroke: #fff;
              stroke-width: 1.7; stroke-linecap: round;
              stroke-linejoin: round; display: block; }
.cr-rail { position: absolute; right: 6px;
           bottom: calc(env(safe-area-inset-bottom, 0px) + 96px);
           z-index: 6; display: flex; flex-direction: column;
           align-items: center; gap: 2px; }
.cr-rail button { background: none; border: 0; padding: 9px;
                  cursor: pointer; line-height: 0; }
.cr-rail svg { width: 27px; height: 27px; fill: none; stroke: #fff;
               stroke-width: 1.7; stroke-linecap: round;
               stroke-linejoin: round; display: block;
               /* white on a bright frame needs its own edge */
               filter: drop-shadow(0 1px 3px rgba(0,0,0,.55)); }
.cr-rail .plike.on svg { stroke: var(--ember); }
.cr-rail .plike.on svg .cf { fill: var(--ember); }
.cr-rail .cr-menu { color: #fff; }
.cr-n { color: rgba(255,255,255,.88); font-size: 12.5px;
        margin: -4px 0 4px; min-height: 15px;
        font-variant-numeric: tabular-nums;
        text-shadow: 0 1px 3px rgba(0,0,0,.55); }
.cr-who { position: absolute; left: 14px; right: 72px;
          bottom: calc(env(safe-area-inset-bottom, 0px) + 40px);
          z-index: 6; }
.cr-hd { display: flex; align-items: center; gap: 9px; }
.cr-hd .av { width: 34px; height: 34px; flex: none; }
.cr-nm { background: none; border: 0; padding: 0; text-align: left;
         cursor: pointer; min-width: 0; }
.cr-nm b { display: block; color: #fff; font-size: 14.5px;
           line-height: 1.25; }
.cr-nm span { display: block; color: rgba(255,255,255,.72);
              font-size: 10.5px; line-height: 1.3; }
.cr-follow { margin-left: 6px; flex: none;
             border: 1px solid rgba(255,255,255,.55);
             background: none; color: #fff; font-size: 11.5px;
             font-weight: 600; border-radius: 999px; padding: 4px 11px;
             cursor: pointer; }
.cr-follow.on { border-color: transparent;
                color: rgba(255,255,255,.65); }
.cr-cap { color: rgba(255,255,255,.92); font-size: 14px;
          line-height: 1.45; margin-top: 9px; cursor: pointer;
          display: -webkit-box; -webkit-line-clamp: 2;
          -webkit-box-orient: vertical; overflow: hidden; }
.cr-cap.open { display: block; -webkit-line-clamp: none;
               max-height: 40vh; overflow-y: auto; }
.cr-cap b { color: #fff; }
/* the scrub. A 2.5px line to read, a 30px band to grab: the line the
   thumb aims at is not the target the thumb has to hit. Under the
   thumb the line thickens and a knob comes out to meet it. */
.cr-scrub { position: absolute; left: 0; right: 0;
            bottom: calc(env(safe-area-inset-bottom, 0px) + 9px);
            z-index: 7; height: 30px; padding: 0 14px;
            display: flex; align-items: center;
            touch-action: none; cursor: pointer; }
.cr-prog { position: relative; flex: 1; height: 2.5px; border-radius: 2px;
           background: rgba(255,255,255,.22); transform-origin: center;
           transition: transform var(--d-tap) var(--e-out); }
.cr-prog i { display: block; height: 100%; width: 0; border-radius: 2px;
             background: rgba(255,255,255,.9); }
.cr-slide.scrubbing .cr-prog { transform: scaleY(2.4); }
.cr-knob { position: absolute; left: 14px; top: 50%;
           width: 13px; height: 13px; margin: -6.5px 0 0 -6.5px;
           border-radius: 50%; background: #fff; opacity: 0;
           pointer-events: none; transition: opacity var(--d-tap) var(--e-out); }
.cr-slide.scrubbing .cr-knob { opacity: 1; }
.cr-time { position: absolute; left: 0; right: 0; bottom: 26px;
           text-align: center; color: rgba(255,255,255,.92);
           font-size: 12px; font-variant-numeric: tabular-nums;
           opacity: 0; pointer-events: none; transition: opacity var(--d-tap) var(--e-out); }
.cr-time i { font-style: normal; color: rgba(255,255,255,.55); }
.cr-slide.scrubbing .cr-time { opacity: 1; }
/* under the thumb the frame is the whole point: the rest steps back */
.cr-slide.scrubbing .cr-who, .cr-slide.scrubbing .cr-rail {
  opacity: 0; pointer-events: none; }
/* a paused clip says so, or the tap that stopped it reads as a stall */
.cr-slide.paused::after { content: ""; position: absolute; left: 50%;
  top: 50%; z-index: 5; width: 0; height: 0; margin: -17px 0 0 -12px;
  border-left: 26px solid rgba(255,255,255,.92);
  border-top: 17px solid transparent;
  border-bottom: 17px solid transparent;
  filter: drop-shadow(0 2px 10px rgba(0,0,0,.5));
  pointer-events: none; }
/* the chip when the browser refused sound: still muted, one tap away */
.cr-snd.want { background: rgba(255,255,255,.3); }
/* a page's pager: a photo is shown whole, type gets the cream card */
.cr-slide .cr-cov.cr-fit { object-fit: contain; }
/* the card stops short of the rail: white icons on cream read as
   nothing at all, and a card sliding under them looks like a mistake */
.cr-txtwrap { position: absolute; inset: 0; display: grid;
              place-items: center; padding: 96px 66px 150px 20px; }
.cr-txtwrap .lb-txt { width: 100%; max-width: 420px; }
/* one tap on a still puts the chrome away, the same as the photo room */
.crbox .cr-top, .crbox .cr-bot, .crbox .cr-rail, .crbox .cr-who,
.crbox .cr-x { transition: opacity var(--d-tap) var(--e-out); }
.crbox.min .cr-top, .crbox.min .cr-bot, .crbox.min .cr-rail,
.crbox.min .cr-who, .crbox.min .cr-x { opacity: 0; pointer-events: none; }
.cr-hint { position: absolute; left: 0; right: 0;
           bottom: calc(env(safe-area-inset-bottom, 0px) + 64px);
           z-index: 7; text-align: center;
           color: rgba(255,255,255,.6); font-size: 11.5px;
           pointer-events: none; animation: crhint 2.4s ease infinite; }
.cr-hint svg { width: 16px; height: 16px; fill: none;
               stroke: rgba(255,255,255,.6); stroke-width: 1.8;
               stroke-linecap: round; stroke-linejoin: round;
               display: block; margin: 0 auto 2px; }
@keyframes crhint { 0%, 100% { transform: translateY(0); }
                    50% { transform: translateY(-6px); } }
.cr-endcard { display: grid; place-items: center; text-align: center;
              padding: 40px; }
.cr-endcup { display: block; width: 44px; height: 44px;
             margin: 0 auto 18px; }
.cr-endcup svg { width: 100%; height: 100%; fill: none;
                 stroke: var(--cream); stroke-width: 1.5;
                 stroke-linecap: round; stroke-linejoin: round; }
.cr-endcard h2 { font-family: var(--serif); font-weight: 400;
                 color: var(--cream); font-size: 27px;
                 letter-spacing: -.2px; margin: 0; }
.cr-endcard p { color: rgba(244,240,231,.66); font-size: 13.5px;
                line-height: 1.55; margin: 12px 0 26px; }

@media (prefers-reduced-motion: reduce) {
  .crbox { transition: none; }
  .cr-hint { animation: none; }
  .cr-prog, .cr-knob, .cr-time { transition: none; }
  .pdev .pdevcov { animation: none; }
}

/* ---------------------------------------------- people to follow (R5)
   The shelf on the Floor tab, the once-per-edition card, the cold-start
   band, and the mutual chips. Nothing here carries a number. */
/* The row runs to the edges of the screen and the cards are sized so
   two and a bit fit, always. At a fixed 156px the third card showed as a
   nine pixel sliver against the page margin, which reads as a rendering
   fault rather than an invitation to scroll: nobody swipes a row that
   looks finished. The bleed is the page padding given back (18px each
   side, matched by the padding here so the first card still lines up
   with the heading above it), and the width is a fraction of the row, so
   the peek holds from a 320px phone to a 430px one. */
/* scroll-padding, not just padding: a snap position is measured from the
   scrollport edge, so without it the first card snapped flush to the
   screen and pulled the row 18px out of line with its own heading. */
.sgrow { display: flex; gap: 10px; overflow-x: auto; padding: 2px 18px 6px;
         margin: 0 -18px 4px; scrollbar-width: none;
         scroll-snap-type: x proximity; scroll-padding-inline: 18px; }
.sgrow::-webkit-scrollbar { display: none; }
.sgc { flex: none; width: calc((100% - 20px) / 2.4);
       scroll-snap-align: start; background: var(--paper);
       border: 1px solid var(--line); border-radius: 18px;
       padding: 16px 12px 12px; text-align: center; position: relative;
       box-shadow: var(--shadow); display: flex; flex-direction: column;
       align-items: center; }
.sgc .av { width: 58px; height: 58px; font-size: 20px; margin: 0 0 9px;
           border: 0; cursor: pointer; }
.sgc .sgnm { background: none; border: 0; padding: 0; font: inherit;
             font-size: 14px; font-weight: 600; letter-spacing: -.1px;
             color: var(--ink); cursor: pointer; }
.sgc .sgwhy { display: block; color: var(--muted); font-size: 11.5px;
              line-height: 1.4; margin: 4px 0 11px; min-height: 32px; }
.sgc .sgfollow { width: 100%; margin-top: auto; }
.sgc .sgfollow.on { background: var(--ground); color: var(--muted);
                    border-color: var(--line); }
.sgx { position: absolute; top: 6px; right: 6px; width: 26px; height: 26px;
       border: 0; background: none; padding: 4px; cursor: pointer;
       color: var(--muted); }
.sgx svg { width: 100%; height: 100%; fill: none; stroke: currentColor;
           stroke-width: 1.8; stroke-linecap: round; display: block; }
.sgcard { padding: 14px 14px 6px; margin: 14px 0; }
.sghd { display: flex; justify-content: space-between;
        align-items: baseline; margin-bottom: 6px; }
.sghd span:last-child { font-size: 12px; color: var(--muted); }
.sgeyebrow { font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
             text-transform: uppercase; color: var(--ink-2); }
.sgr { padding: 9px 0; }
/* the reason is the whole point of the row: it wraps, never clips */
.sgr .dsub { white-space: normal; overflow: visible; text-overflow: clip;
             line-height: 1.35; }
.sgr + .sgr { border-top: 1px solid var(--line-soft); }
.sgcold { margin-top: 16px; }
.sgcold h3 { font-family: var(--serif); font-weight: 400; font-size: 20px;
             letter-spacing: -.2px; margin: 0 0 4px; }
.sgcold .sub { margin: 0 0 10px; }
.fy { display: inline-block; margin-left: 6px; font-size: 10px;
      font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
      color: var(--ink-2); background: var(--ground);
      border: 1px solid var(--line); border-radius: 999px;
      padding: 2px 7px; vertical-align: middle; font-family: var(--sans); }
.pcname .fy { color: #fff; background: rgba(255,255,255,.16);
              border-color: rgba(255,255,255,.45); }
.mut { display: flex; align-items: center; gap: 6px; margin-top: 4px;
       color: var(--good); font-size: 12.5px; font-weight: 600;
       font-family: var(--sans); letter-spacing: 0; }
.mut svg { width: 15px; height: 15px; fill: none; stroke: currentColor;
           stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.pcname .mut { color: #d9efe3; }

/* the invited line at the top of the Lobby. It lands after its own
   fetch, so it rises in rather than appearing mid-screen out of
   nothing; it is the only thing on this screen that moves. */
.lbhi { background: #fffaf0; border: 1px solid #f2dc9e;
        border-radius: var(--r-lg); padding: 15px 17px; margin: 0 0 18px;
        animation: lbhi-in .34s var(--e-out) both; }
.lbhi b { display: block; font-family: var(--serif); font-weight: 400;
          font-size: 19px; line-height: 1.25; letter-spacing: -.2px;
          color: var(--ink); }
.lbhi span { display: block; margin-top: 6px; font-size: 13.5px;
             line-height: 1.5; color: var(--ink-2); }
@keyframes lbhi-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) { .lbhi { animation: none; } }

/* ----------------------------------------------- bring someone in (R6) */
.rfh { font-family: var(--serif); font-weight: 400; font-size: 19px;
       margin: 0 0 8px; letter-spacing: -.2px; }
.rflink { display: flex; align-items: center; gap: 10px; background: var(--ground);
          border: 1px solid var(--line); border-radius: 14px; padding: 11px 12px;
          font-size: 12.5px; color: var(--ink-2); margin-bottom: 10px; }
.rflink span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis;
               white-space: nowrap; }
.rfcopy { background: none; border: 0; padding: 0; font: inherit; font-size: 12px;
          font-weight: 700; color: var(--ink); cursor: pointer; }
/* the one action, and the other two ways kept quiet under it */
.rfone { padding-bottom: 14px; }
.rfnote { margin: 10px 2px 0; font-size: 13px; line-height: 1.45; }
.rfalt { display: flex; flex-wrap: wrap; gap: 4px 6px; margin: 12px 0 0;
         align-items: center; }
.rfalt button { background: none; border: 0; padding: 6px 2px; font: inherit;
                font-size: 12.5px; color: var(--ink-2); cursor: pointer;
                text-decoration: underline; text-underline-offset: 3px;
                text-decoration-color: var(--line);
                transition: color var(--d-tap) var(--e-out),
                            transform var(--d-tap) var(--e-out); }
.rfalt button + button { margin-left: 8px; }
.rfalt button:active { transform: scale(var(--press-btn)); color: var(--ink); }
.rfalt button.on { color: var(--ink); font-weight: 600; }
.rfmailbox { margin-top: 12px; }
@media (hover: hover) { .rfalt button:hover { color: var(--ink); } }
@media (prefers-reduced-motion: reduce) { .rfalt button { transition: none; } }
.rffield { display: flex; gap: 8px; }
.rffield input { flex: 1; min-width: 0; border: 1px solid var(--line);
                 border-radius: 999px; padding: 11px 14px; font: inherit;
                 font-size: 14px; background: var(--paper); }
.rfsteps { counter-reset: s; margin: 0; padding: 0; list-style: none; }
.rfsteps li { display: flex; gap: 12px; align-items: flex-start; padding: 9px 0;
              border-top: 1px solid var(--line-soft); font-size: 13.5px;
              line-height: 1.45; }
.rfsteps li:first-child { border-top: 0; padding-top: 2px; }
.rfsteps li::before { counter-increment: s; content: counter(s); flex: none;
                      width: 26px; height: 26px; border-radius: 50%;
                      background: var(--ink); color: var(--cream); display: grid;
                      place-items: center; font-size: 12px; font-weight: 700; }
.rfsteps b { display: block; }
.rfsteps small { color: var(--muted); font-size: 12.5px; }
.rfsteps b.gold, .rfpts.gold { color: #8a6400; }
.rfpeople { padding-top: 4px; padding-bottom: 4px; }
.rfrow { display: flex; align-items: center; gap: 12px; padding: 11px 0;
         border-top: 1px solid var(--line-soft); }
.rfrow:first-child { border-top: 0; }
.rfrow .av { width: 40px; height: 40px; flex: none; font-size: 14px; }
.rfbd { flex: 1; min-width: 0; }
.rfbd .nm { display: block; font-size: 14px; font-weight: 600; }
.rfst { display: block; color: var(--muted); font-size: 12px; margin-top: 2px; }
.rfstage { display: flex; gap: 4px; margin-top: 6px; max-width: 180px; }
.rfstage i { flex: 1; height: 4px; border-radius: 999px; background: var(--line); }
.rfstage i.on { background: var(--ink); }
.rfstage i.gold { background: var(--accent); }
.rfpts { margin-left: auto; text-align: right; font-size: 13px; font-weight: 700;
         white-space: nowrap; flex: none; }
.rfpts small { display: block; font-weight: 400; color: var(--muted); font-size: 11px; }
.rfpts.muted { color: var(--muted); }
.linkish { background: none; border: 0; padding: 0; font: inherit; color: var(--ink);
           text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.aic.gold { background: #fff4cf; border-color: #f2dc9e; }

/* The Floor's door, for a guest (2026-08-21). The floor is the members'
   room now, so the two floor tabs answer with one card instead of a
   half-screen. It reads as an invitation, not a refusal: plain words and
   one gold action. A watermark of the house mark was tried and cut -- at
   card size it cropped to a fragment that read as a stray line. */
.gatecard {
  position: relative;
  overflow: hidden;
  padding: 22px 20px 20px;
}
.gatecard h3 {
  margin: 0 0 6px;
  font-family: var(--serif);
  font-size: 21px;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.gatecard p {
  margin: 0 0 16px;
  color: var(--muted);
  font-size: 14.5px;
  line-height: 1.55;
  max-width: 34ch;
}
.gatecard .btn {
  position: relative;
  z-index: 1;
}

/* ------------------------------------------------------------- Mentors
   Paid access to a person who has done the thing (2026-08-21). The list
   and the page are quiet on purpose: what is being sold is a person's
   judgement, and a loud card selling it reads like an ad for a course.
   One gold action per screen, and the price is never the biggest thing
   on it. */
.mtdoor {
  display: flex; align-items: center; gap: 12px;
  width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--line); background: var(--paper);
}
.mtdoor b { font-family: var(--serif); font-size: 17px; display: block; }
.mtdoor i {
  font-style: normal; color: var(--muted); font-size: 13.5px;
  line-height: 1.45; display: block; margin-top: 2px;
}
.mtdoor > span:first-of-type, .mtdoor > b { flex: 0 0 auto; }
.mtdoor .mtgo { margin-left: auto; flex: 0 0 auto; opacity: .5; }
.mtdoor > b, .mtdoor > i { flex: 1 1 auto; }

.mtcard, .mtthread {
  display: block; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--line); background: var(--paper);
}
.mtrow { display: flex; align-items: center; gap: 12px; }
.mtrow .av {
  width: 44px; height: 44px; border-radius: 50%; flex: 0 0 44px;
  display: flex; align-items: center; justify-content: center;
  background: var(--cream); font-size: 14px; font-weight: 600;
  overflow: hidden; color: var(--ink-2);
}
.mtrow .av img { width: 100%; height: 100%; object-fit: cover; }
.mtwho { min-width: 0; }
.mtwho b { display: block; font-size: 16px; }
.mtwho i {
  font-style: normal; display: block; color: var(--muted);
  font-size: 13.5px; line-height: 1.4; margin-top: 1px;
}
.mtdot {
  margin-left: auto; background: var(--ember); color: #fff;
  border-radius: 999px; min-width: 22px; height: 22px; padding: 0 6px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 700;
}
.mttags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; }
.mttags i {
  font-style: normal; font-size: 12px; color: var(--muted);
  border: 1px solid var(--line); border-radius: 999px; padding: 3px 9px;
}
.mtfoot {
  display: flex; align-items: baseline; gap: 8px; margin-top: 12px;
  padding-top: 10px; border-top: 1px solid var(--line-soft);
  font-size: 13.5px;
}
.mtfoot b { font-size: 15px; }
.mtfoot i { font-style: normal; color: var(--muted); margin-left: auto; }

.mtwant { color: var(--muted); font-size: 13.5px; margin: -4px 0 14px; }
.mtwant b { color: var(--ink); }
.mtblock { line-height: 1.62; white-space: normal; }
.mtpage .mtrow .av { width: 56px; height: 56px; flex-basis: 56px; }

.mtoffer .mtoh {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px; margin-bottom: 6px;
}
.mtoffer .mtoh b { font-family: var(--serif); font-size: 17px; }
.mtoffer .mtoh span { color: var(--muted); font-size: 14px; }
.mtoffer p { color: var(--muted); font-size: 14px; line-height: 1.55;
             margin: 0 0 14px; }
.mtoffer .mtnote { color: var(--ink-2); }
.mtacts { display: flex; flex-wrap: wrap; gap: 8px; }
.mtacts .btn { flex: 1 1 auto; }
.mtfine { color: var(--muted); font-size: 12.5px; line-height: 1.5;
          margin: 10px 2px 0; }

.mtmine { border-color: var(--accent); }

/* The thread. The promise sits above it, for both of them. */
.mtclock {
  background: var(--cream); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 12px 14px; font-size: 13.5px;
  color: var(--ink-2); margin-bottom: 14px;
}
.mtclock.late { border-color: var(--warn); color: var(--warn); }
.mtmsgs { display: flex; flex-direction: column; gap: 10px; }
.mtmsg {
  align-self: flex-start; max-width: 84%;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 16px 16px 16px 4px; padding: 11px 14px;
  font-size: 15px; line-height: 1.5;
  /* the message is text, held as text: the newlines are the sheet's job
     now, not a <br> built into the string */
  white-space: pre-wrap; overflow-wrap: break-word;
}
.mtmsg.me {
  align-self: flex-end; background: var(--night); color: #f3f1ea;
  border-color: var(--night); border-radius: 16px 16px 4px 16px;
}
.mtsys {
  align-self: center; color: var(--muted); font-size: 12.5px;
  text-align: center; max-width: 80%;
}
.mtsend { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
.mtsend textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 12px 14px; font: inherit; font-size: 15px; background: var(--paper);
  resize: vertical;
}

/* The interview. One question a card, the example under it. */
.mtprog {
  height: 3px; background: var(--line); border-radius: 3px;
  margin: 0 2px 18px; overflow: hidden;
}
.mtprog i { display: block; height: 100%; background: var(--accent);
            transition: width var(--d-travel) var(--e-soft); }
.mtq h3 { font-family: var(--serif); font-size: 18px; margin: 0 0 4px; }
.mtq .sub { margin: 0 0 12px; font-size: 13.5px; }
.mtq textarea, .mtoffer textarea {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 12px 14px; font: inherit; font-size: 15px; line-height: 1.55;
  background: var(--ground); resize: vertical;
}
.mteg { color: var(--muted); font-size: 12.5px; line-height: 1.5;
        margin: 10px 2px 0; font-style: italic; }
.mtband { background: var(--cream); border-color: var(--line); }
.mtband h3 { font-family: var(--serif); font-size: 17px; margin: 0 0 2px; }
.mtbandn { font-family: var(--serif); font-size: 26px; margin: 0 0 10px; }
.mtband ul { margin: 0; padding-left: 18px; color: var(--ink-2);
             font-size: 13.5px; line-height: 1.6; }
.mtprice {
  width: 84px; border: 1px solid var(--line); border-radius: 10px;
  padding: 4px 8px; font: inherit; font-size: 14px; text-align: right;
  background: var(--paper);
}
.mtsw { display: flex; align-items: center; gap: 8px; margin-top: 12px;
        font-size: 14px; color: var(--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .mtprog i { transition: none; }
}

/* ------------------------------------------------- the mentor intake
   One question a screen (2026-08-22). These answers become the page a
   stranger reads before paying, and a stack of boxes gets a stack of
   one-line answers; a single question with the whole screen behind it
   gets a paragraph. The screen is quiet so the question is not. */
.mtstep {
  display: flex; flex-direction: column; gap: 0;
  /* A floor only. The real height is measured in mtFit(), because the
     chrome and the tab bar are different on every phone and a guess
     here puts the last line under the tabs. */
  min-height: calc(100dvh - 250px);
  opacity: 1;
}
@media (prefers-reduced-motion: no-preference) {
  .mtstep { opacity: 0; transform: translateY(10px); }
  .mtstep.in {
    opacity: 1; transform: none;
    transition: opacity var(--d-travel) var(--e-soft),
                transform var(--d-travel) var(--e-soft);
  }
}

.mtbar { display: flex; align-items: center; gap: 14px; padding: 4px 0 26px; }
.mtx {
  width: 34px; height: 34px; border-radius: 50%; border: 0;
  background: transparent; display: flex; align-items: center;
  justify-content: center; cursor: pointer; color: var(--ink);
  margin-left: -8px; transition: background var(--d-tap) var(--e-out);
}
.mtx:active { background: var(--line-soft); transform: scale(var(--press-ico)); }
.mtpips { display: flex; gap: 5px; flex: 1; }
.mtpips i {
  height: 3px; flex: 1; border-radius: 3px; background: var(--line);
  transition: background var(--d-enter) var(--e-soft);
}
.mtpips i.done { background: var(--ink-2); }
.mtpips i.now { background: var(--accent); }

.mtcentre { display: flex; flex-direction: column; flex: 1; }
.mtbig {
  font-family: var(--serif); font-weight: 400; font-size: 34px;
  line-height: 1.14; letter-spacing: -.5px; margin: 8px 0 14px;
  text-wrap: balance;
}
.mtlede {
  color: var(--muted); font-size: 16px; line-height: 1.55;
  margin: 0 0 30px; max-width: 30ch;
}
.mtfacts { display: flex; flex-direction: column; gap: 1px;
           background: var(--line); border: 1px solid var(--line);
           border-radius: var(--r-lg); overflow: hidden; margin-bottom: auto; }
.mtfacts div { background: var(--paper); padding: 14px 16px; }
.mtfacts b { display: block; font-size: 15px; }
.mtfacts i { font-style: normal; display: block; color: var(--muted);
             font-size: 13.5px; margin-top: 2px; }

.mtask { display: flex; flex-direction: column; flex: 1; }
.mtq2 {
  font-family: var(--serif); font-weight: 400; font-size: 27px;
  line-height: 1.2; letter-spacing: -.3px; margin: 0 0 10px;
  text-wrap: balance;
}
.mthint { color: var(--muted); font-size: 14.5px; line-height: 1.55;
          margin: 0 0 20px; max-width: 34ch; }
.mtin {
  width: 100%; border: 0; border-bottom: 1px solid var(--line);
  background: transparent; padding: 4px 0 12px; font: inherit;
  font-size: 17px; line-height: 1.6; resize: none; color: var(--ink);
  transition: border-color var(--d-tap) var(--e-out);
}
.mtin:focus { outline: 0; border-bottom-color: var(--ink); }
.mtin::placeholder { color: var(--muted); opacity: .6; }

/* The reason the step will not advance, said once they have tried. */
.mtshort {
  margin: 0; font-size: 13.5px; line-height: 1.5; color: var(--ember);
  max-height: 0; overflow: hidden; opacity: 0;
  transition: opacity var(--d-tap) var(--e-out),
              max-height var(--d-enter) var(--e-soft),
              margin-top var(--d-enter) var(--e-soft);
}
.mtshort.on { max-height: 80px; opacity: 1; margin-top: 10px; }
@media (prefers-reduced-motion: reduce) {
  .mtshort { transition: none; }
}

/* One quiet row under the field: a way to start, then the example.
   Both are aids, neither writes the answer, so they read the same
   weight and sit on the same line. */
.mtaids {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 0 0;
}
.mtaid {
  border: 0; background: transparent; padding: 0; color: var(--muted);
  font: inherit; font-size: 13.5px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
  transition: color var(--d-tap) var(--e-out);
}
.mtaid:active { color: var(--ink); }
.mtaid.lead { color: var(--ink-2); }
/* .mtsep, not .mtdot: .mtdot is already the unread badge on a
   mentorship row (ember pill, margin-left:auto), and reusing the name
   turned the separator into a red circle that shoved the two links to
   opposite ends of the row. */
.mtsep { color: #c3bfb2; font-size: 13.5px; }

/* The composer. Same disclosure as the example, because it is the same
   promise: something to push off from, not something to hand in. */
.mtbuild {
  max-height: 0; overflow: hidden; opacity: 0;
  transition: max-height var(--d-travel) var(--e-soft),
              opacity var(--d-enter) var(--e-out),
              margin-top var(--d-travel) var(--e-soft);
}
.mtbuild.open { max-height: 560px; opacity: 1; margin-top: 14px; }
.mtbrow { display: flex; flex-direction: column; gap: 2px;
          margin-bottom: 12px; }
.mtbrow label { font-size: 12.5px; color: var(--muted); }
.mtbrow input {
  width: 100%; border: 0; border-bottom: 1px solid var(--line);
  background: transparent; padding: 5px 0 8px; font: inherit;
  font-size: 16px; color: var(--ink);
  transition: border-color var(--d-tap) var(--e-out);
}
.mtbrow input:focus { outline: 0; border-bottom-color: var(--ink); }
.mtbrow input::placeholder { color: var(--muted); opacity: .55; }
.mtdraft {
  border-left: 2px solid var(--accent); padding-left: 14px;
  font-size: 14.5px; line-height: 1.6; color: var(--ink-2);
  margin: 16px 0 0;
}
.mtdraft.empty { color: var(--muted); }
.mtuse { margin-top: 14px; display: flex; align-items: center; gap: 12px; }
@media (prefers-reduced-motion: reduce) {
  .mtbuild { transition: none; }
}

.mteg2 {
  align-self: flex-start; border: 0; background: transparent; padding: 12px 0;
  color: var(--muted); font: inherit; font-size: 13.5px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 3px;
}
.mtegbox {
  max-height: 0; overflow: hidden; color: var(--ink-2); font-size: 14px;
  line-height: 1.6; font-style: italic;
  border-left: 2px solid var(--accent); padding-left: 0; opacity: 0;
  transition: max-height var(--d-enter) var(--e-soft),
              opacity var(--d-enter) var(--e-out),
              padding var(--d-enter) var(--e-soft),
              margin-top var(--d-enter) var(--e-soft);
}
.mtegbox.open { max-height: 260px; opacity: 1; padding-left: 14px;
               margin-top: 12px; }

.mttagwrap { justify-content: flex-start; margin-bottom: auto; }
.mtfootbar { margin-top: auto; padding-top: 28px;
             display: flex; flex-direction: column; gap: 4px; }
.mtlink {
  border: 0; background: transparent; color: var(--muted); font: inherit;
  font-size: 14px; padding: 12px; cursor: pointer;
}
.mtfootbar .btn[disabled] { opacity: .38; }

.mtrev {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 13px 15px; margin-bottom: 8px;
  transition: transform var(--d-tap) var(--e-out);
}
.mtrev:active { transform: scale(var(--press-row)); }
.mtrev b { display: block; font-size: 13px; color: var(--muted);
           font-weight: 500; margin-bottom: 4px; }
.mtrev span { display: block; font-size: 14.5px; line-height: 1.5;
              color: var(--ink); }
.mtref { margin-top: 14px; }
.mtref input { margin-bottom: 8px; }

.mtbandc {
  display: flex; flex-direction: column; gap: 4px; margin-top: 20px;
  background: var(--cream); border-radius: var(--r-lg); padding: 16px 18px;
}
.mtbandk { font-size: 13px; color: var(--muted); }
.mtbandc .mtbandn { font-family: var(--serif); font-size: 27px; margin: 0; }
.mtbandc ul { margin: 6px 0 0; padding-left: 18px; color: var(--ink-2);
              font-size: 13.5px; line-height: 1.6; }
.mtbandc .mtfine { margin: 8px 0 0; }

/* ------------------------------------------------------------- Cafe 295
   Ordering from the cafe on this floor. Reuses the house tokens; the
   only new shapes are a menu row, a category strip and the bar that
   sits over the tab bar once there is something in the cart.

   Motion is deliberately almost absent here. This is a list somebody
   scrolls at lunchtime with one thumb, and a menu that animates while
   you are trying to read the price of a sandwich is worse than a still
   one. What does move is press feedback, and it uses the house curve. */

.cafcard .btn { margin-top: 2px; }

/* Where it goes. A row, not a form field: it is answered once and then
   it is a fact you can tap to change. */
.cafsuite {
  width: 100%; display: flex; align-items: baseline; gap: 8px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px; margin: 14px 0 10px;
  text-align: left; transition: transform var(--d-tap) var(--e-out);
}
.cafsuite span { color: var(--muted); font-size: 14px; }
.cafsuite b { margin-left: auto; font-size: 15px; }
.cafsuite:active { transform: scale(var(--press-row)); }

/* The categories. Twenty-two of them, so this scrolls sideways and
   never wraps into a wall of chips. */
.cafcats {
  display: flex; gap: 8px; overflow-x: auto; padding: 2px 0 10px;
  margin: 0 -18px; padding-left: 18px; padding-right: 18px;
  scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.cafcats::-webkit-scrollbar { display: none; }
.cafcat {
  flex: none; border: 1px solid var(--line); background: var(--paper);
  color: var(--ink-2); border-radius: 999px; padding: 7px 14px;
  font-size: 14px; white-space: nowrap;
  transition: transform var(--d-tap) var(--e-out),
              background var(--d-tap) var(--e-out);
}
.cafcat:active { transform: scale(var(--press-btn)); }
.cafcat.on {
  background: var(--ink); color: var(--cream); border-color: var(--ink);
}

.caflist { display: flex; flex-direction: column; gap: 8px; }

.cafrow {
  display: grid; grid-template-columns: 56px 1fr auto; gap: 12px;
  align-items: center; text-align: left;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 10px 14px 10px 10px;
  transition: transform var(--d-tap) var(--e-out);
}
.cafrow:active { transform: scale(var(--press-row)); }
.cafthumb {
  width: 56px; height: 56px; border-radius: var(--r-sm);
  object-fit: cover; background: var(--line-soft); display: block;
}
.cafthumb.none { background: var(--line-soft); }
.cafmeta { min-width: 0; display: block; }
.cafmeta b {
  display: block; font-size: 15px; font-weight: 600; line-height: 1.3;
}
.cafmeta i {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-style: normal; color: var(--muted);
  font-size: 13px; line-height: 1.4; margin-top: 2px;
}
.cafprice { font-size: 15px; font-weight: 600; white-space: nowrap; }

/* The cart rides in the chrome, not over the menu (Fahad, 2026-08-22:
   the bar at the bottom sat on the last row's text). The chrome is
   already sticky, so it is reachable the whole way down a long menu
   without anything covering what is being read. */
.chip.cartchip { gap: 5px; padding-left: 9px; }
.chip.cartchip span { color: var(--muted); font-weight: 500; }
.carticon {
  width: 15px; height: 15px; display: block; fill: none;
  stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Inside the item sheet. */
.cafgrp { margin: 14px 0 0; }
.cafglab {
  display: block; font-size: 13px; color: var(--muted); margin-bottom: 6px;
}
.cafopt {
  display: flex; align-items: center; gap: 10px; padding: 9px 0;
  border-bottom: 1px solid var(--line-soft); font-size: 15px;
}
.cafopt:last-child { border-bottom: 0; }
.cafopt input { width: 20px; height: 20px; accent-color: var(--ink); }
.cafopt span { flex: 1; min-width: 0; }
.cafopt b { color: var(--muted); font-weight: 500; font-size: 14px; }
.cafnote, .cafsuitein {
  width: 100%; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); padding: 11px 12px; font-size: 16px;
  font-family: var(--sans); color: var(--ink);
}
.cafsuitein { margin: 6px 0 14px; }
.cafqty {
  display: flex; align-items: center; justify-content: center; gap: 20px;
  margin: 18px 0 14px;
}
.cafqty button {
  width: 40px; height: 40px; border-radius: 999px; font-size: 20px;
  border: 1px solid var(--line); background: var(--paper);
  transition: transform var(--d-tap) var(--e-out);
}
.cafqty button:active { transform: scale(var(--press-ico)); }
.cafqty b { font-size: 18px; min-width: 26px; text-align: center; }

/* The order, in the review sheet. */
.cafline {
  display: flex; align-items: flex-start; gap: 10px; padding: 11px 0;
  border-bottom: 1px solid var(--line-soft); font-size: 15px;
}
.cafline > span { flex: 1; min-width: 0; }
.cafline i {
  display: block; font-style: normal; color: var(--muted);
  font-size: 13px; margin-top: 2px;
}
.cafx {
  border: 0; background: none; color: var(--muted); font-size: 20px;
  line-height: 1; padding: 0 2px; transition: transform var(--d-tap) var(--e-out);
}
.cafx:active { transform: scale(var(--press-ico)); }
.caftot {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 12px 0 0; font-size: 15px;
}
.caftot span { color: var(--muted); }
.caftot b { font-size: 17px; }

@media (prefers-reduced-motion: reduce) {
  .cafsuite, .cafcat, .cafrow, .cafqty button, .cafx { transition: none; }
}

/* The group's name, said once, where the menu changes from food to
   drinks. A label, not a chip: it is not tappable and must not look it. */
.cafgroup {
  flex: none; align-self: center; padding: 0 4px 0 6px;
  font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); white-space: nowrap;
}
.cafcats > .cafgroup:first-child { padding-left: 0; }

/* Where it goes and when it comes, side by side. Two facts, both
   answered once, both tappable to change. */
.cafwhere { display: flex; gap: 8px; margin: 14px 0 10px; }
.cafwhere .cafsuite { margin: 0; flex: 1; min-width: 0; display: block; }
.cafwhere .cafsuite span { display: block; }
.cafwhere .cafsuite b { display: block; margin: 2px 0 0; font-size: 14.5px; }

/* Carried up, or picked up. Two answers to one question, so they are
   radio rows and not a segmented control: each one needs a line of its
   own to say what actually happens. */
.cafwho {
  display: flex; gap: 12px; align-items: flex-start; width: 100%;
  text-align: left; background: var(--ground);
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 13px 14px; margin: 0 0 10px;
  transition: transform var(--d-tap) var(--e-out),
              border-color var(--d-tap) var(--e-out),
              background-color var(--d-tap) var(--e-out);
}
.cafwho:active { transform: scale(var(--press-row)); }
.cafwho.on { background: var(--paper); border-color: var(--ink); }
.cafwho b { display: block; font-size: 15px; font-weight: 600; }
.cafwho i { display: block; font-style: normal; font-size: 13px;
            color: var(--muted); margin-top: 2px; }
.cafdot {
  width: 19px; height: 19px; border-radius: 50%; flex: none;
  margin-top: 2px; border: 1.5px solid var(--line);
  display: grid; place-items: center;
  transition: border-color var(--d-tap) var(--e-out);
}
.cafwho.on .cafdot { border-color: var(--ink); }
.cafwho.on .cafdot::after {
  content: ""; width: 9px; height: 9px; border-radius: 50%;
  background: var(--ink);
}
/* The suite box belongs to the option above it, so it is indented to
   the width of that option's dot and gutter. */
.cafsuitewrap { margin-left: 31px; }
.cafsuitewrap[hidden] { display: none; }
.cafsuitewrap .cafsuitein { margin: 0 0 10px; }

@media (prefers-reduced-motion: reduce) {
  .cafwho, .cafdot { transition: none; }
}

/* Choosing a time. */
.cafnow {
  width: 100%; text-align: left; background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 12px 14px; margin: 0 0 14px; font-size: 15px;
  transition: transform var(--d-tap) var(--e-out),
              border-color var(--d-tap) var(--e-out);
}
.cafnow i { display: block; font-style: normal; color: var(--muted);
            font-size: 13px; margin-top: 2px; }
.cafnow:active { transform: scale(var(--press-row)); }
.cafnow.on { border-color: var(--ink); }
.cafdays {
  display: flex; gap: 8px; overflow-x: auto; padding-bottom: 4px;
  scrollbar-width: none;
}
.cafdays::-webkit-scrollbar { display: none; }
.cafdays .cafcat[disabled] { opacity: .38; }
.cafslots {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  margin-top: 14px; max-height: 44vh; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
.cafslot {
  border: 1px solid var(--line); background: var(--paper);
  border-radius: var(--r-sm); padding: 10px 4px; font-size: 14px;
  transition: transform var(--d-tap) var(--e-out);
}
.cafslot:active { transform: scale(var(--press-ico)); }
.cafslot.on { background: var(--ink); color: var(--cream);
              border-color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .cafnow, .cafslot { transition: none; }
}

/* A group Square marks SINGLE: one choice, drawn as radios so the ticket
   cannot ask for a dine-in cup and a to-go cup at once. */
.cafglab i { font-style: normal; color: var(--muted); opacity: .8; }
.cafopt input[type="radio"] { border-radius: 50%; }

/* ---------------------------------------------------------- the island
   A screen that render() cannot touch (floor.js, Isle). Fixed, full
   bleed, its own scroller, and a footer that rides on top of the
   keyboard instead of under it: `bottom: var(--kb)` shrinks the whole
   island by exactly the height iOS is covering, so the composer is
   always the last thing above the keys and the thread keeps scrolling
   underneath.

   Entry and exit carry DIFFERENT transitions on purpose. Coming in is
   the full house entrance; going out is shorter and accelerates away,
   because by then the person has already decided. Both are transitions,
   not keyframes, so a half-finished swipe back can be caught and
   reversed mid flight. */
.isle {
  position: fixed; inset: 0; bottom: var(--kb); z-index: 80;
  background: var(--cream); display: flex; flex-direction: column;
  transform: translateX(100%);
  transition: transform var(--d-exit) var(--e-exit);
}
.isle.in {
  transform: none;
  transition: transform var(--d-enter) var(--e-out);
}
body.isle-on { overflow: hidden; }

.isle-hd {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: max(10px, env(safe-area-inset-top, 10px)) 14px 10px 6px;
  border-bottom: 1px solid var(--line);
  background: rgba(244, 240, 231, .88);
  backdrop-filter: saturate(1.4) blur(14px);
  -webkit-backdrop-filter: saturate(1.4) blur(14px);
}
.isle-back {
  background: none; border: 0; padding: 8px 10px; line-height: 0;
  border-radius: 999px; color: var(--ink);
  transition: transform var(--d-tap) var(--e-out);
}
.isle-back:active { transform: scale(var(--press-ico)); }
.isle-back svg { width: 22px; height: 22px; fill: none;
                 stroke: currentColor; stroke-width: 1.8;
                 stroke-linecap: round; stroke-linejoin: round; }
.isle-who { min-width: 0; }
.isle-who b { display: block; font-size: 16px; font-weight: 600;
              line-height: 1.2; }
.isle-who i { display: block; font-style: normal; font-size: 12.5px;
              color: var(--muted); margin-top: 1px; }

.isle-scr {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  padding: 14px 16px 8px; display: flex; flex-direction: column; gap: 10px;
  /* A short conversation sits ON the composer, not at the top of an
     empty screen. margin-top on the first child rather than
     justify-content, which puts overflowing content out of reach of the
     scrollbar in Safari. */
  /* new content is appended at the bottom, so the browser should hold
     the bottom, not the top, when the box grows */
  overflow-anchor: auto;
}
.isle-scr > :first-child { margin-top: auto; }

.isle-foot {
  flex: none; border-top: 1px solid var(--line); background: var(--cream);
  /* The island has already shrunk by --kb, so the home-indicator inset
     below it is only there to pad for while the keyboard is down. Once
     the keyboard covers more than the inset, the term goes to zero. */
  padding: 9px 12px
           calc(9px + max(0px, env(safe-area-inset-bottom, 0px) - var(--kb)));
}

.isle-comp { display: flex; align-items: flex-end; gap: 8px; }
.isle-comp textarea {
  flex: 1; min-width: 0; resize: none; font: inherit; font-size: 16px;
  line-height: 1.4; color: var(--ink); background: var(--paper);
  border: 1px solid var(--line); border-radius: 20px;
  padding: 9px 14px; max-height: 124px; overflow-y: auto;
  scrollbar-width: none;
  transition: border-color var(--d-tap) var(--e-out);
}
.isle-comp textarea::-webkit-scrollbar { display: none; }
.isle-comp textarea:focus { outline: 0; border-color: #cdc8b8; }
.isle-send {
  flex: none; width: 34px; height: 34px; border-radius: 50%; border: 0;
  background: var(--ink); color: var(--cream); line-height: 0;
  display: grid; place-items: center; margin-bottom: 2px;
  transition: transform var(--d-tap) var(--e-out),
              opacity var(--d-tap) var(--e-out);
}
.isle-send:active { transform: scale(var(--press-ico)); }
.isle-send[disabled] { opacity: .3; }
.isle-send svg { width: 17px; height: 17px; fill: none;
                 stroke: currentColor; stroke-width: 2;
                 stroke-linecap: round; stroke-linejoin: round; }

.isle-jump {
  position: absolute; left: 50%; bottom: 76px; transform: translateX(-50%);
  z-index: 2; background: var(--ink); color: var(--cream); border: 0;
  border-radius: 999px; padding: 7px 14px; font-size: 13px;
  box-shadow: var(--shadow-lift);
}
.isle-jump[hidden] { display: none; }

/* A message that has not landed yet is not greyed out and does not spin.
   It is simply the message, and the only thing that ever changes is the
   line underneath the last one. */
.isle-state { font-size: 11.5px; color: var(--muted); text-align: right;
              margin: -4px 2px 0; }
.isle-state.bad { color: var(--ember); }
.isle-state button { background: none; border: 0; padding: 0;
                     color: var(--ember); font: inherit;
                     text-decoration: underline; }

/* ------------------------------------------------------------- messages
   Member to member. The inbox is an ordinary screen; the conversation
   lives on the island above it (see .isle). Classes are scoped to this
   block because floor.css is one global sheet: .mtx, .mrow and .run were
   already taken, which is exactly the trap kb/floor.md warns about. */
.msgchip { position: relative; padding: 7px 9px; line-height: 0; }
.msgchip svg { width: 19px; height: 19px; fill: none; stroke: var(--ink);
               stroke-width: 1.7; stroke-linecap: round;
               stroke-linejoin: round; }
/* Unread is a dot, never a number in the chrome: a count on a header
   is a thing to clear, and this app is not trying to be cleared. */
.msgchip::after {
  content: ""; position: absolute; top: 4px; right: 5px;
  width: 7px; height: 7px; border-radius: 50%; background: var(--ember);
  transform: scale(0); transform-origin: center;
  transition: transform var(--d-tap) var(--e-pop);
}
.msgchip.on::after { transform: scale(1); }

.mline {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px 14px; margin-bottom: 9px;
  font: inherit; color: inherit; text-align: left;
  box-shadow: var(--shadow);
  transition: transform var(--d-tap) var(--e-out);
}
.mline:active { transform: scale(var(--press-row)); }
.mwho { min-width: 0; flex: 1; }
.mwho b { display: block; font-size: 15px; font-weight: 600; }
.mwho i { display: block; font-style: normal; font-size: 13.5px;
          color: var(--muted); margin-top: 2px;
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mend { flex: none; display: flex; flex-direction: column;
        align-items: flex-end; gap: 5px; }
.mend > i { font-style: normal; font-size: 12px; color: var(--muted);
            font-variant-numeric: tabular-nums; }
.mdot { min-width: 20px; height: 20px; border-radius: 999px;
        background: var(--ember); color: var(--cream); font-size: 12px;
        font-weight: 600; display: grid; place-items: center;
        padding: 0 6px; }
/* A conversation holding something unread reads louder than the rest:
   the name heavier, the preview in full ink instead of muted, and the
   count pill wears ember so the eye finds it from the top of the list.
   The read rows stay quiet on purpose; the contrast IS the signal. */
.mline.unread .mwho b { font-weight: 700; }
.mline.unread .mwho i { color: var(--ink); font-weight: 500; }
.mline.unread .mend > i { color: var(--ember); font-weight: 600; }
.mmute { font-size: 11px; color: var(--muted); }

.mreq { margin-bottom: 12px; }
.mreqrow { display: flex; align-items: center; gap: 12px; }
.mreqbody { margin: 12px 0 0; font-size: 15.5px; line-height: 1.5;
            white-space: pre-wrap; overflow-wrap: break-word; }
.mreqacts { display: flex; gap: 8px; margin-top: 14px; }
.mreqacts .btn { flex: 1; }

/* ---- the conversation ---- */
.mbw {
  align-self: flex-start; max-width: 84%; position: relative;
  display: flex; flex-direction: column; align-items: flex-start;
}
.mbw.me { align-self: flex-end; align-items: flex-end; }
/* A run of lines from the same person inside three minutes reads as one
   turn in the conversation, so it is drawn as one. */
.isle-scr > .mbw.mbrun { margin-top: -6px; }
.mb {
  /* Capped, or a nowrap quote inside it pushes the bubble past the
     84% the wrapper allows and off the edge of the screen. */
  max-width: 100%; min-width: 0;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: 18px 18px 18px 5px; padding: 9px 13px;
  font-size: 16px; line-height: 1.45;
  white-space: pre-wrap; overflow-wrap: break-word;
  transition: transform var(--d-tap) var(--e-out);
}
.mb.me { background: var(--night); color: #f3f1ea; border-color: var(--night);
         border-radius: 18px 18px 5px 18px; }
.mbw.mbrun .mb { border-radius: 18px; }
.mb.gone { background: transparent; border-style: dashed;
           color: var(--muted); font-style: italic; }
.mb.gone.me { background: transparent; color: var(--muted);
              border-color: var(--line); }
.mbw.flash .mb { animation: mflash 1.1s var(--e-out); }
@keyframes mflash {
  0% { box-shadow: 0 0 0 3px rgba(255,200,56,.85); }
  100% { box-shadow: 0 0 0 3px rgba(255,200,56,0); }
}
/* Swiping right on a bubble reveals the reply mark it is heading for. */
.mbw::before {
  content: ""; position: absolute; left: -30px; top: 50%;
  width: 18px; height: 18px; margin-top: -9px; opacity: 0;
  background: no-repeat center/contain
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236e6d68' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M9 14 4 9l5-5'/><path d='M4 9h9a7 7 0 0 1 7 7v3'/></svg>");
  transition: opacity var(--d-tap) var(--e-out);
}
.mbw.armed::before { opacity: 1; }

.mq {
  display: block; width: 100%; max-width: 100%; text-align: left;
  background: none;
  border: 0; border-left: 2px solid currentColor; padding: 0 0 0 8px;
  margin: 0 0 5px; font: inherit; font-size: 13.5px; line-height: 1.4;
  opacity: .62; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.mbtx { display: block; }
.mmk { display: none; gap: 3px; margin: -6px 6px 0; }
.mmk.has { display: flex; }
.mmk i { font-style: normal; font-size: 13px; line-height: 1;
         background: var(--paper); border: 1px solid var(--line);
         border-radius: 999px; padding: 3px 6px; }
.mmk i.on { border-color: var(--ink); }
.mmk i[data-n]::after { content: attr(data-n); font-size: 11px;
                        margin-left: 3px; color: var(--muted); }
/* The landed cup is the house cup, filled ember (kb/messages.md, the
   pour). It pops into place on the same curve every mark uses. */
.mmk i.cup { padding: 3px 7px;
             transition: transform var(--d-tap) var(--e-pop),
                         opacity var(--d-press) var(--e-out); }
.mmk i.cup svg { display: block; width: 15px; height: 15px; fill: none;
                 stroke: var(--ink); stroke-width: 1.7;
                 stroke-linecap: round; stroke-linejoin: round; }
.mmk i.cup svg .cf { fill: var(--ember); }
.mmk i.cup.hold { opacity: 0; transform: scale(.5); transition: none; }

/* ---- the pour ----
   Fire-once celebration, so keyframes are allowed; transform and
   opacity only, one clipPath. The JS skips it under reduced motion and
   this block is the belt to those braces. */
.mpour { position: absolute; width: 58px; height: 58px; z-index: 6;
         pointer-events: none; }
.mpour svg { width: 100%; height: 100%; overflow: visible; fill: none;
             stroke: var(--ink); stroke-width: 1.5;
             stroke-linecap: round; stroke-linejoin: round; }
.mpour .mp-cup { opacity: 0; transform: scale(.6);
                 transform-origin: 50% 70%;
                 animation: mp-in 240ms var(--e-pop) forwards; }
.mpour .mp-stream { stroke: var(--ember); stroke-width: 2.2;
                    transform: scaleY(0); transform-origin: 11px 0;
                    animation: mp-pour 200ms 120ms var(--e-out) forwards,
                               mp-cut 170ms 720ms var(--e-exit) forwards; }
.mpour .mp-liquid { fill: var(--ember); stroke: none;
                    transform: translateY(9px);
                    animation: mp-rise 620ms 200ms var(--e-soft) forwards; }
.mpour .mp-steam { opacity: 0;
                   animation: mp-steam 560ms 780ms var(--e-soft) forwards; }
.mpour .mp-steam.s2 { animation-delay: 880ms; }
.mpour .mp-glint { fill: rgba(255,255,255,.5); stroke: none; opacity: 0;
                   transform: translateX(-12px) rotate(18deg);
                   animation: mp-glint 300ms 900ms var(--e-inout) forwards; }
.mpour.settle { transition: transform 240ms var(--e-out),
                            opacity 200ms var(--e-out);
                transform: translateY(26px) scale(.3); opacity: 0; }
/* The filmed pour: the clip circle-cropped at the corner. The entrance
   animation rides on the video so the outer div stays free for the
   settle transition (an animation's fill would out-cascade it). */
.mpour.vid { width: 76px; height: 76px; border-radius: 50%;
             overflow: hidden;
             box-shadow: 0 0 0 2px var(--card),
                         0 6px 18px rgba(60, 40, 20, .28); }
.mpour.vid video { width: 100%; height: 100%; object-fit: cover;
                   display: block; opacity: 0; transform: scale(.6);
                   transform-origin: 50% 70%;
                   animation: mp-in 240ms var(--e-pop) forwards; }
@keyframes mp-in { to { opacity: 1; transform: scale(1); } }
@keyframes mp-pour { to { transform: scaleY(1); } }
@keyframes mp-cut { from { transform: scaleY(1);
                           transform-origin: 11px 100%; }
                    to { transform: scaleY(0);
                         transform-origin: 11px 100%; } }
@keyframes mp-rise { to { transform: translateY(0); } }
@keyframes mp-steam { 0% { opacity: 0; transform: translateY(3px); }
                      45% { opacity: .9; }
                      100% { opacity: 0; transform: translateY(-5px); } }
@keyframes mp-glint { 0% { opacity: 0;
                           transform: translateX(-12px) rotate(18deg); }
                      35% { opacity: 1; }
                      100% { opacity: 0;
                             transform: translateX(14px) rotate(18deg); } }
@media (prefers-reduced-motion: reduce) { .mpour { display: none; } }
.mday { align-self: center; font-size: 12px; color: var(--muted);
        letter-spacing: .04em; margin: 8px 0 2px; }
.mtime { font-size: 11.5px; color: var(--muted); margin: 3px 4px 0; }
.mseen { font-size: 11.5px; color: var(--muted); margin: 3px 4px 0;
         align-self: flex-end; }

.mtyping { align-self: flex-start; display: flex; gap: 4px;
           background: var(--paper); border: 1px solid var(--line);
           border-radius: 18px; padding: 11px 13px; }
.mtyping i { width: 6px; height: 6px; border-radius: 50%;
             background: var(--muted); opacity: .4;
             animation: mtdot 1.1s ease-in-out infinite; }
.mtyping i:nth-child(2) { animation-delay: .15s; }
.mtyping i:nth-child(3) { animation-delay: .3s; }
@keyframes mtdot {
  0%, 60%, 100% { opacity: .3; transform: none; }
  30% { opacity: .9; transform: translateY(-3px); }
}

/* ---- the long press menu ----
   It grows from the corner of the bubble that was held, never from its
   own centre, and never from scale(0). */
body.mdim::after {
  content: ""; position: fixed; inset: 0; z-index: 88;
  background: rgba(23,23,22,.28);
  animation: mdimin var(--d-enter) var(--e-out) both;
}
@keyframes mdimin { from { opacity: 0; } to { opacity: 1; } }
.mmenu {
  position: fixed; z-index: 89; left: var(--mx); top: var(--my);
  width: max-content; max-width: min(280px, 78vw);
  transform: translate(0, -100%) scale(.95); opacity: 0;
  transform-origin: bottom left;
  transition: transform var(--d-enter) var(--e-out),
              opacity var(--d-tap) var(--e-out);
}
.mmenu[data-side="me"] { transform: translate(-100%, -100%) scale(.95);
                         transform-origin: bottom right; }
.mmenu.in { opacity: 1; transform: translate(0, -100%) scale(1); }
.mmenu.in[data-side="me"] { transform: translate(-100%, -100%) scale(1); }
.mmarks { display: flex; gap: 2px; background: var(--paper);
          border: 1px solid var(--line); border-radius: 999px;
          padding: 5px 6px; box-shadow: var(--shadow-lift);
          margin-bottom: 8px; }
.mmarks button { background: none; border: 0; font-size: 21px;
                 line-height: 1; padding: 5px 6px; border-radius: 999px;
                 transition: transform var(--d-tap) var(--e-pop); }
.mmarks button:active { transform: scale(1.22); }
.macts { background: var(--paper); border: 1px solid var(--line);
         border-radius: 14px; overflow: hidden;
         box-shadow: var(--shadow-lift); }
.macts button { display: block; width: 100%; text-align: left;
                background: none; border: 0; font: inherit; font-size: 15px;
                padding: 12px 16px; color: var(--ink); }
.macts button + button { border-top: 1px solid var(--line-soft); }
.macts button:active { background: var(--line-soft); }
.macts button.bad { color: var(--ember); }

/* ---- the reply strip, above the composer ---- */
.mrep { display: flex; align-items: center; gap: 10px; padding: 0 4px 8px; }
.mrep span { flex: 1; min-width: 0; font-size: 13.5px; color: var(--muted);
             border-left: 2px solid var(--accent); padding-left: 8px;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mrep button { background: none; border: 0; font-size: 20px; line-height: 1;
               color: var(--muted); padding: 2px 6px; }

.isle-more { margin-left: auto; background: none; border: 0;
             padding: 10px 12px; display: flex; gap: 3px;
             align-items: center;
             transition: transform var(--d-tap) var(--e-out); }
.isle-more:active { transform: scale(var(--press-ico)); }
.isle-more span { width: 4px; height: 4px; border-radius: 50%;
                  background: var(--ink-2); display: block; }

/* ---- messages V1: rooms, the desk, photos ---- */
.mline.staff { border-color: #d9d2bd; background: #fbf7ec; }
.mdesk-av, .mgrp-av {
  width: 40px; height: 40px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: var(--line-soft); color: var(--ink-2);
}
.mdesk-av { background: var(--night); color: var(--cream); }
.mdesk-av svg, .mgrp-av svg { width: 20px; height: 20px; fill: none;
  stroke: currentColor; stroke-width: 1.7; stroke-linecap: round;
  stroke-linejoin: round; }
.mkind { font-style: normal; font-weight: 400; font-size: 11.5px;
         color: var(--muted); margin-left: 6px; letter-spacing: .02em;
         text-transform: uppercase; }

/* whose line this is, in a room; the desk's version is the house */
.mwhotag { display: block; font-style: normal; font-size: 12px;
           color: var(--muted); margin: 2px 6px 3px; }
.mwhotag.staff { color: var(--warn); font-weight: 600; }
.mb.staffmb { background: #fbf7ec; border-color: #e5dcc2; }

/* the group maker */
.mgppl { max-height: 42vh; overflow-y: auto; border: 1px solid var(--line);
         border-radius: var(--r-md); background: var(--paper); }
.mgp { display: flex; align-items: center; gap: 12px; width: 100%;
       background: none; border: 0; padding: 11px 14px; font: inherit;
       color: inherit; text-align: left;
       transition: background var(--d-tap) var(--e-out); }
.mgp + .mgp { border-top: 1px solid var(--line-soft); }
.mgp:active { background: var(--line-soft); }
.mgp span { flex: 1; min-width: 0; overflow: hidden;
            text-overflow: ellipsis; white-space: nowrap; }
.mgtick { width: 22px; height: 22px; border-radius: 50%; flex: none;
          border: 1.6px solid var(--line); position: relative;
          transition: background var(--d-tap) var(--e-out),
                      border-color var(--d-tap) var(--e-out); }
.mgp.on .mgtick { background: var(--ink); border-color: var(--ink); }
.mgtick::after { content: ""; position: absolute; inset: 0;
  background: no-repeat center/12px
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23f4f0e7' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5 10 17.5 19 7'/></svg>");
  opacity: 0; transform: scale(.6);
  transition: opacity var(--d-tap) var(--e-pop),
              transform var(--d-tap) var(--e-pop); }
.mgp.on .mgtick::after { opacity: 1; transform: scale(1); }

/* the photo button in the composer */
.isle-pic { flex: none; width: 34px; height: 34px; border-radius: 50%;
            border: 0; background: none; color: var(--muted);
            display: grid; place-items: center; margin-bottom: 2px;
            transition: transform var(--d-tap) var(--e-out); }
.isle-pic:active { transform: scale(var(--press-ico)); }
.isle-pic svg { width: 21px; height: 21px; fill: none;
                stroke: currentColor; stroke-width: 1.7;
                stroke-linecap: round; stroke-linejoin: round; }

/* a photo in a bubble */
.mb.haspic { padding: 4px; }
.mb.haspic .mbtx { padding: 6px 9px 5px; display: block; }
.mpic { display: block; max-width: 100%; width: 240px; max-height: 320px;
        object-fit: cover; border-radius: 15px; cursor: zoom-in; }

/* the photo room */
.mpicroom { position: fixed; inset: 0; z-index: 95;
            background: rgba(16,24,22,.96); display: grid;
            place-items: center; opacity: 0;
            transition: opacity var(--d-enter) var(--e-out);
            padding: env(safe-area-inset-top, 10px) 10px
                     env(safe-area-inset-bottom, 10px); }
.mpicroom.in { opacity: 1; }
.mpicroom img { max-width: 100%; max-height: 100%; border-radius: 8px; }

.mrep span.edit { border-left-color: var(--good); font-weight: 600;
                  color: var(--good); }
.mtyping b { font-weight: 400; font-size: 12px; color: var(--muted);
             margin-right: 6px; }

/* ---- room faces + the group maker's head ---- */
.mghead { display: flex; gap: 12px; align-items: flex-end; }
.mgface {
  flex: none; width: 52px; height: 52px; border-radius: 50%;
  border: 1.6px dashed #c9c4b4; background: var(--paper);
  display: grid; place-items: center; color: var(--muted);
  overflow: hidden; padding: 0;
  transition: transform var(--d-tap) var(--e-out);
}
.mgface:active { transform: scale(var(--press-ico)); }
.mgface svg { width: 22px; height: 22px; fill: none; stroke: currentColor;
              stroke-width: 1.7; stroke-linecap: round;
              stroke-linejoin: round; }
.mgface img { width: 100%; height: 100%; object-fit: cover; }
.mroom-av { width: 40px; height: 40px; border-radius: 50%; flex: none;
            object-fit: cover; border: 1px solid var(--line); }

/* ---- V1.5: moving forward, impact, the sort button ---- */
.mvcard { text-align: left; font: inherit; color: inherit; }
.mvcard b { font-size: 15.5px; }
.mvcard.wide { display: block; width: 100%; }
.mvimpact { font-size: 14px; color: var(--ink-2); margin: 0 2px 10px;
            line-height: 1.5; }
.answer .asort { display: block; margin-top: 8px; }
.aic.gold { background: var(--accent); }
.aic.gold svg { stroke: var(--accent-ink); }

/* ---- the Later row: voice notes, growth, the summary ---- */
.mb.hasvoice { padding: 6px 8px; }
.vnote {
  display: flex; align-items: center; gap: 9px; min-width: 190px;
  background: none; border: 0; padding: 4px 6px; font: inherit;
  color: inherit;
}
.vngo { width: 30px; height: 30px; border-radius: 50%; flex: none;
        background: var(--accent); color: var(--accent-ink);
        display: grid; place-items: center;
        transition: transform var(--d-tap) var(--e-out); }
.vnote:active .vngo { transform: scale(var(--press-ico)); }
.vngo svg { width: 15px; height: 15px; fill: currentColor; stroke: none; }
.vnote.playing .vngo svg { fill: none; stroke: currentColor;
                           stroke-width: 2.4; stroke-linecap: round; }
.vnbar { flex: 1; height: 3px; border-radius: 3px;
         background: rgba(110,109,104,.35); overflow: hidden; }
.mb.me .vnbar { background: rgba(243,241,234,.3); }
.vnbar i { display: block; height: 100%; width: 0; border-radius: 3px;
           background: currentColor; }
.vnote time { font-size: 12px; font-variant-numeric: tabular-nums;
              opacity: .75; }

/* GIFs (2026-08-24). The button wears its own name: three letters read
   faster than any icon a GIF has ever been given. */
.isle-gy i { font-style: normal; font-size: 10.5px; font-weight: 700;
             letter-spacing: .04em; line-height: 1;
             border: 1.6px solid currentColor; border-radius: 5px;
             padding: 3px 3.5px 2.5px; }
.isle-gy.on { color: var(--ink); }

/* The picker: a strip above the composer, grown from the button that
   opened it (transform-origin), never from its own middle. */
.gyp { padding: 0 2px 8px; opacity: 0;
       transform: translateY(6px) scale(.97);
       transform-origin: 100% 100%;
       transition: opacity var(--d-enter) var(--e-out),
                   transform var(--d-enter) var(--e-out); }
.gyp.on { opacity: 1; transform: none; }
.gyhd { display: flex; align-items: center; gap: 8px; padding: 0 2px 8px; }
.gyq { flex: 1; min-width: 0; height: 34px; padding: 0 12px;
       border: 1px solid var(--line); border-radius: 999px;
       background: var(--paper); color: var(--ink);
       font: inherit; font-size: 15px; }
.gyq:focus { outline: 0; border-color: #cdc8b8; }
.gyq::-webkit-search-cancel-button { display: none; }
.gyx { flex: none; width: 30px; height: 30px; border: 0; border-radius: 50%;
       background: none; color: var(--muted); display: grid;
       place-items: center;
       transition: transform var(--d-tap) var(--e-out); }
.gyx:active { transform: scale(var(--press-ico)); }
.gyx svg { width: 18px; height: 18px; fill: none; stroke: currentColor;
           stroke-width: 1.8; stroke-linecap: round; }
/* One row, scrolled sideways: it sits on top of a keyboard, so height
   is the scarce thing and a grid would push the composer off screen. */
.gyrow { display: flex; gap: 8px; overflow-x: auto; overflow-y: hidden;
         -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity;
         padding: 2px; min-height: 104px; align-items: center; }
.gyrow::-webkit-scrollbar { display: none; }
.gycell { flex: none; height: 100px; width: calc(100px * var(--gyar, 1.3));
          max-width: 62vw; padding: 0; border: 0; border-radius: 12px;
          overflow: hidden; background: var(--line-soft);
          scroll-snap-align: start;
          transition: transform var(--d-tap) var(--e-out); }
.gycell:active { transform: scale(var(--press-btn)); }
.gycell img { display: block; width: 100%; height: 100%;
              object-fit: cover; }
.gynote { margin: 0 auto; padding: 0 8px; color: var(--muted);
          font-size: 14px; text-align: center; }
.gyby { margin: 6px 2px 0; font-size: 10.5px; letter-spacing: .06em;
        text-transform: uppercase; color: var(--muted); }

/* A GIF in a bubble: our own silent mp4, sized like a photo. */
.gybub { display: block; max-width: 100%; width: 220px; max-height: 300px;
         object-fit: cover; border-radius: 15px; background: var(--line-soft); }
/* A GIF sent by itself: no bubble, no ink, just the art. */
.mb.gyonly { padding: 0; background: none; box-shadow: none; border: 0; }
.mb.gyonly .gybub { border-radius: var(--r-md); }
/* .mb.haspic .mbtx is display:block for a caption under a photo, which
   beats the hidden attribute and leaves an empty strip under art that
   has no words. A GIF alone has none by definition. */
.mb.gyonly .mbtx[hidden] { display: none; }
.gyhold { position: relative; display: inline-block; }
.gyplay { position: absolute; inset: auto 8px 8px auto; width: 34px;
          height: 34px; border: 0; border-radius: 50%;
          background: rgba(23,23,22,.62); color: #fff;
          display: grid; place-items: center; }
.gyplay svg { width: 16px; height: 16px; fill: currentColor;
              margin-left: 2px; }

.vrec { display: flex; align-items: center; gap: 10px; padding: 0 4px 8px; }
.vrdot { width: 10px; height: 10px; border-radius: 50%; flex: none;
         background: var(--ember);
         animation: vrpulse 1.2s ease-in-out infinite; }
@keyframes vrpulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .vrdot { animation: none; } }
.vrec time { flex: 1; font-variant-numeric: tabular-nums; font-size: 14px; }
.btn.sm { padding: 8px 14px; font-size: 13.5px; }

/* The label sits ABOVE its value, not in a 7.2em gutter beside it. That
   gutter was a third of the card and it was why a one line goal wrapped
   at six words. */
.about { padding: 2px 16px; }
.abrow { padding: 13px 0; }
.abrow + .abrow { border-top: 1px solid var(--line-soft); }
.abrow i { display: block; font-style: normal; font-size: 10.5px;
           letter-spacing: .11em; text-transform: uppercase;
           color: var(--muted); margin-bottom: 6px; }
.abrow b { display: block; font-family: var(--serif); font-weight: 500;
           font-size: 19px; line-height: 1.35; letter-spacing: -.005em; }
.abset { display: flex; flex-wrap: wrap; gap: 6px; }
.abset .tag { font-style: normal; }
.abwork { margin: 0; font-size: 15px; line-height: 1.4; }
.abwork + .abwork { margin-top: 4px; }
.abwork b { display: inline; font-family: var(--sans); font-weight: 600;
            font-size: 15px; }
.abwork span { color: var(--muted); }
.about .pworkcup { margin-bottom: 14px; }

.asumwrap { margin-bottom: 12px; }
.asum { background: var(--cream); border: 1px solid var(--line);
        border-radius: var(--r-md); padding: 13px 15px; font-size: 14.5px;
        line-height: 1.55; white-space: pre-wrap; }
.asum i { display: block; margin-top: 9px; font-size: 12px;
          color: var(--muted); }
.asum.note { background: none; border: 0; padding: 4px 2px;
             color: var(--muted); font-size: 13.5px; }

/* ---- the push invitation ---- */
.pinvwho { display: flex; align-items: center; gap: 12px;
           margin: 2px 0 14px; }
.pinvwho .av { width: 40px; height: 40px; flex: none; }
.pinvwho b { display: block; font-size: 15px; letter-spacing: -.01em; }
.pinvwho small { color: var(--muted); font-size: 12.5px; }
.pinvp { font-size: 14.5px; line-height: 1.55; margin: 0 0 6px; }
.pinvq { color: var(--muted); font-size: 12.5px; line-height: 1.5;
         margin: 0 0 18px; }
.btn.pinvlater { margin-top: 4px; color: var(--muted); border: 0;
                 font-weight: 500; }
.pinvsteps { display: flex; flex-direction: column; gap: 10px;
             margin: 12px 0 14px; }
.pinvstep { display: flex; align-items: center; gap: 14px;
            background: var(--cream); border: 1px solid var(--line);
            border-radius: 14px; padding: 12px 14px; text-align: left; }
.pinvstep > span:last-child { font-size: 14px; }
.pinvstep small { display: block; color: var(--muted); font-size: 12px;
                  margin-top: 1px; }
.pinvic { width: 34px; height: 34px; border-radius: 9px; flex: none;
          background: var(--paper); border: 1px solid var(--line);
          display: flex; align-items: center; justify-content: center; }
.pinvic svg { width: 18px; height: 18px; stroke: #0a84ff;
              stroke-width: 1.8; fill: none; stroke-linecap: round;
              stroke-linejoin: round; }

/* ------------------------------------------------- the member mark (R8)
   The house J on a small cream seal, beside the name of anyone on a
   monthly invoice right now. Ink, never gold (gold means money here).
   Absent, not negative: nobody is ever marked as not a member. */
.jpseal { display: inline-flex; align-items: center; justify-content: center;
          width: 16px; height: 16px; border-radius: 50%;
          background: var(--ground); border: 1px solid var(--line);
          vertical-align: -2.5px; margin-left: 5px; flex: none; }
.jpseal svg { width: 8px; height: 11.5px; display: block; }
.jpseal svg path { fill: var(--ink); }
/* on the clip room's dark ground the seal keeps its own cream field */
.cr-nm .jpseal { border-color: rgba(255,255,255,.35); }
/* the one place it says the words: the member page card */
.jpchip { display: inline-flex; align-items: center; gap: 6px;
          margin-top: 8px; padding: 4px 10px 4px 5px;
          background: var(--ground); border: 1px solid var(--line);
          border-radius: 999px; font-size: 11px; font-weight: 600;
          letter-spacing: .05em; text-transform: uppercase;
          color: var(--ink-2); font-family: var(--sans); }
.jpchip .jpseal { margin: 0; width: 17px; height: 17px;
                  background: var(--paper); vertical-align: 0; }
.jpchip .jpseal svg { width: 8px; height: 11.5px; }
/* over a cover photo the chip sits on the scrim, so it goes glassy the
   same way the Follows-you chip does there */
.pcscrim .jpchip { color: #fff; background: rgba(255,255,255,.16);
                   border-color: rgba(255,255,255,.45); }
.pcscrim .jpchip .jpseal { background: rgba(255,255,255,.92);
                           border-color: transparent; }

/* ------------------------------------------------- Pieces (design R8)
   Long-form writing in the one feed: the card collapses to a serif
   title and a two-line excerpt, and the Reader is a full-screen cream
   room where typography is the whole product. */
.peye { display: flex; align-items: center; gap: 7px;
        font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase;
        color: var(--muted); font-weight: 700; }
.peye i { width: 14px; height: 1px; background: var(--accent); }
.ppt { font-family: var(--serif); font-size: 21px; line-height: 1.22;
       font-weight: 600; margin: 7px 0 6px; color: var(--ink); }
.ppx { font-family: var(--serif); font-size: 15px; line-height: 1.5;
       color: var(--ink-2); display: -webkit-box; -webkit-line-clamp: 2;
       -webkit-box-orient: vertical; overflow: hidden; }
.ppopen { display: block; width: 100%; text-align: left; border: 0;
          background: none; padding: 12px 16px 2px; }
.ppread { display: inline-block; border: 1px solid var(--line);
          border-radius: 999px; padding: 3px 10px; font-size: 12px;
          color: var(--ink-2); background: var(--ground); }

.rdbox { position: fixed; inset: 0; z-index: 55; background: var(--cream);
         opacity: 0; transform: translateY(14px);
         transition: opacity var(--d-enter) var(--e-out),
                     transform var(--d-enter) var(--e-out); }
.rdbox.in { opacity: 1; transform: none; }
.rdbox.out { opacity: 0; transform: translateY(60px);
             transition: opacity var(--d-exit) var(--e-exit),
                         transform var(--d-exit) var(--e-exit); }
.rd-thread { position: absolute; top: 0; left: 0; right: 0; height: 3px;
             z-index: 8; background: var(--accent); transform-origin: 0 0;
             transform: scaleX(0); }
.rd-scroll { height: 100%; overflow-y: auto;
             -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
             padding: 0 22px calc(40px + env(safe-area-inset-bottom, 0px)); }
.rd-top { position: sticky; top: 0; z-index: 6; display: flex;
          align-items: center; justify-content: space-between;
          padding: calc(env(safe-area-inset-top, 0px) + 14px) 0 8px;
          background: linear-gradient(var(--cream) 72%,
                                      rgba(244,240,231,0)); }
.rd-top .tk2 { font-size: 11px; letter-spacing: .16em;
               text-transform: uppercase; color: var(--muted);
               font-weight: 700; }
.rd-x { border: 0; background: none; padding: 6px; color: var(--ink); }
.rd-x svg, .rd-fwd svg { width: 22px; height: 22px; fill: none;
                         stroke: currentColor; stroke-width: 1.8;
                         stroke-linecap: round; stroke-linejoin: round; }
.rd-fwd { border: 0; background: none; padding: 6px; color: var(--ink); }
.rd-title { font-family: var(--serif); font-size: 29px; line-height: 1.18;
            font-weight: 600; margin: 8px 0 14px; max-width: 34em; }
.rd-by { display: flex; align-items: center; gap: 10px; margin: 0 0 16px; }
.rd-by .vfollow { margin-left: auto; }
.rd-cover { border-radius: var(--r-md); overflow: hidden; margin: 0 0 18px; }
.rd-cover img { display: block; width: 100%; height: auto; }
.rd-body { font-family: var(--serif); font-size: 17px; line-height: 1.62;
           color: var(--ink); max-width: 62ch; margin: 0 auto; }
.rd-body p { margin: 0 0 1em; overflow-wrap: break-word; }
.rd-end { max-width: 62ch; margin: 22px auto 0; }
.rd-cups { display: flex; gap: 16px; align-items: center;
           padding: 16px 0; border-top: 1px solid var(--line);
           border-bottom: 1px solid var(--line-soft); margin-bottom: 14px; }
.rd-more { display: flex; align-items: center; gap: 12px; width: 100%;
           background: var(--paper); border: 0; text-align: left;
           border-radius: var(--r-lg); box-shadow: var(--shadow);
           padding: 14px 16px; margin-top: 14px; }
.rd-more b { font-family: var(--serif); font-size: 16px; display: block; }
.rd-more span { color: var(--muted); font-size: 13px; }

/* the writing room */
.wrbox { position: fixed; inset: 0; z-index: 55; background: var(--cream);
         display: flex; flex-direction: column; opacity: 0;
         transform: translateY(14px);
         transition: opacity var(--d-enter) var(--e-out),
                     transform var(--d-enter) var(--e-out); }
.wrbox.in { opacity: 1; transform: none; }
.wrbox.out { opacity: 0; transform: translateY(60px);
             transition: opacity var(--d-exit) var(--e-exit),
                         transform var(--d-exit) var(--e-exit); }
.wr-in { flex: 1; display: flex; flex-direction: column; min-height: 0;
         padding: 0 22px; }
.wr-title { font-family: var(--serif); font-size: 26px; font-weight: 600;
            border: 0; background: none; outline: none; color: var(--ink);
            margin: 8px 0 2px; width: 100%; }
.wr-title::placeholder { color: #b9b5a9; }
.wr-cover { border: 0; background: none; color: var(--muted);
            font-size: 13px; padding: 4px 0 8px; text-align: left; }
.wr-cover.has { color: var(--good); }
.wr-body { flex: 1; min-height: 0; border: 0; background: none;
           outline: none; resize: none; font-family: var(--serif);
           font-size: 17px; line-height: 1.6; color: var(--ink);
           padding: 6px 0 12px; }
.wr-body::placeholder { color: #b9b5a9; }
.wr-foot { display: flex; align-items: center; justify-content:
           space-between; padding: 10px 0
           calc(18px + env(safe-area-inset-bottom, 0px)); }
.wr-count { color: var(--muted); font-size: 12.5px;
            font-variant-numeric: tabular-nums; }
.wr-count.hot { color: var(--warn); }

/* ------------------------------------------- the Idea Room (design R8)
   The pitch pinned on top, the wall below: short signed cards through
   three doors. Offers wear the gold hairline; a sparked card takes the
   gilt corner and rises to its own band. */
.stepin { display: flex; align-items: center; justify-content:
          space-between; border-top: 1px solid var(--line-soft);
          padding: 11px 16px; }
.stepin .faces { display: flex; }
.stepin .faces .av { width: 24px; height: 24px; font-size: 11px;
                     margin-left: -8px; box-shadow: 0 0 0 2px var(--paper); }
.stepin .faces .av:first-child { margin-left: 0; }
.stepin .n { color: var(--muted); font-size: 12.5px; margin-left: 10px; }
.stepbtn { background: var(--ink); color: var(--cream); border: 0;
           border-radius: 999px; padding: 8px 16px; font-size: 13.5px;
           font-weight: 600; }
.pout { background: var(--ink); color: var(--cream);
        border-radius: var(--r-md); padding: 11px 14px; font-size: 13.5px;
        margin: 10px 16px 0; line-height: 1.4; }
.pout b { font-family: var(--serif); font-size: 15px; }

.irbox { position: fixed; inset: 0; z-index: 55; background: var(--cream);
         opacity: 0; transform: translateY(14px);
         transition: opacity var(--d-enter) var(--e-out),
                     transform var(--d-enter) var(--e-out); }
.irbox.in { opacity: 1; transform: none; }
.irbox.out { opacity: 0; transform: translateY(60px);
             transition: opacity var(--d-exit) var(--e-exit),
                         transform var(--d-exit) var(--e-exit); }
.ir-scroll { height: 100%; overflow-y: auto;
             -webkit-overflow-scrolling: touch; overscroll-behavior: contain;
             padding: 0 14px calc(84px + env(safe-area-inset-bottom, 0px)); }
.ir-pitch { background: var(--paper); border-radius: var(--r-lg);
            box-shadow: var(--shadow); padding: 16px; margin-bottom: 4px; }
.ir-state { font-size: 11px; letter-spacing: .16em;
            text-transform: uppercase; font-weight: 700;
            color: var(--good); }
.ir-state.closed { color: var(--muted); }
.ir-pt { font-family: var(--serif); font-size: 19px; line-height: 1.25;
         font-weight: 600; margin: 10px 0 6px; }
.ir-px { font-family: var(--serif); font-size: 15.5px; line-height: 1.5;
         color: var(--ink-2); overflow-wrap: break-word; }
.ir-band { font-size: 11px; letter-spacing: .16em;
           text-transform: uppercase; font-weight: 700;
           color: var(--muted); margin: 14px 2px 8px; }
.ir-wall { columns: 2; column-gap: 11px; }
.ir-wall.one { columns: 1; }
.ir-card { background: var(--paper); border-radius: var(--r-md);
           box-shadow: var(--shadow); padding: 12px 13px;
           margin-bottom: 11px; break-inside: avoid; font-size: 13.5px;
           line-height: 1.42; color: var(--ink-2); position: relative;
           overflow: hidden; overflow-wrap: break-word;
           animation: ircIn var(--d-enter) var(--e-out) both;
           animation-delay: calc(var(--i, 0) * 24ms); }
@keyframes ircIn { from { opacity: 0; transform: translateY(10px); }
                   to { opacity: 1; transform: none; } }
.ir-card.offer { border: 1px solid var(--accent); }
.ir-card.sparked::before { content: ""; position: absolute; top: 0;
        right: 0; border-top: 16px solid var(--accent);
        border-left: 16px solid transparent; }
.ir-who { display: flex; align-items: center; gap: 7px; font-weight: 600;
          font-size: 12.5px; color: var(--ink); margin-bottom: 6px; }
.ir-who .av { width: 22px; height: 22px; font-size: 10px; flex: 0 0 auto; }
.ir-who .nm { border: 0; background: none; padding: 0; font: inherit;
              color: inherit; min-width: 0; overflow: hidden;
              text-overflow: ellipsis; white-space: nowrap; }
.ir-k { font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
        font-weight: 700; border-radius: 999px; padding: 2px 8px;
        background: var(--ground); color: var(--muted); margin-left: auto;
        flex: 0 0 auto; }
.ir-card.offer .ir-k { background: var(--accent); color: var(--ink); }
.ir-foot { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.ir-cup { border: 0; background: none; padding: 0; color: var(--muted);
          font-size: 12px; display: inline-flex; align-items: center;
          gap: 5px; transition: transform var(--d-press) var(--e-out); }
.ir-cup:active { transform: scale(var(--press-ico, .9)); }
.ir-cup svg { width: 15px; height: 15px; fill: none; stroke: currentColor;
              stroke-width: 1.8; stroke-linecap: round;
              stroke-linejoin: round; }
.ir-cup.on { color: var(--ember); }
.ir-cup.on svg .cf { fill: var(--ember); stroke: var(--ember); }
.ir-more2 { border: 0; background: none; padding: 0 0 0 4px;
            color: var(--muted); margin-left: auto; font-size: 15px;
            line-height: 1; }
.ir-doors { position: absolute; left: 14px; right: 14px;
            bottom: calc(14px + env(safe-area-inset-bottom, 0px));
            display: flex; gap: 9px; z-index: 6; }
.ir-door { flex: 1; background: var(--paper); border: 1px solid
           var(--line); border-radius: 999px; padding: 12px 0;
           text-align: center; font-size: 13px; font-weight: 600;
           box-shadow: var(--shadow);
           transition: transform var(--d-press) var(--e-out); }
.ir-door:active { transform: scale(var(--press-btn, .97)); }
.ir-door.offer { background: var(--ink); color: var(--cream);
                 border-color: var(--ink); }
.ir-closedbar { position: absolute; left: 14px; right: 14px;
                bottom: calc(14px + env(safe-area-inset-bottom, 0px));
                z-index: 6; text-align: center; color: var(--muted);
                font-size: 12.5px; background: var(--ground);
                border: 1px solid var(--line); border-radius: 999px;
                padding: 11px 0; }
.ir-new { position: absolute; left: 50%; transform: translate(-50%, 0);
          top: calc(env(safe-area-inset-top, 0px) + 52px); z-index: 7;
          background: var(--ink); color: var(--cream);
          border: 0; border-radius: 999px; padding: 7px 14px;
          font-size: 12.5px; font-weight: 600; box-shadow: var(--shadow); }

@media (prefers-reduced-motion: reduce) {
  .rdbox, .wrbox, .irbox { transition: opacity 1ms linear; transform: none; }
  .rdbox.out, .wrbox.out, .irbox.out { transform: none; }
  .ir-card { animation: none; }
}

/* the Reader's end-of-piece cup rides the feed's cup styles without
   living inside a .pact row */
.rd-cups .plike { background: none; border: 0; padding: 6px;
                  line-height: 0; border-radius: 999px;
                  transition: transform var(--d-tap) var(--e-out); }
.rd-cups .plike:active { transform: scale(var(--press-ico)); }
.rd-cups .plike svg { width: 26px; height: 26px; fill: none;
                      stroke: var(--ink); stroke-width: 1.65;
                      stroke-linecap: round; stroke-linejoin: round; }
.rd-cups .plike.on svg { stroke: var(--ember); }
.rd-cups .plike.on svg .cf { fill: var(--ember); }
.rd-cups .plike.pop svg { animation: heartpop .34s var(--e-pop); }
.rd-cups .flk { display: none; }

/* ------------------------------------------------- R9: networking.
   Titles, professions, skills, and the coffee ask. */
.otn { display: inline-block; margin-left: 6px; font-size: 10px;
       font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
       color: var(--good); background: transparent;
       border: 1px solid currentColor; border-radius: 999px;
       padding: 2px 7px; vertical-align: middle; font-family: var(--sans); }
.pcname .otn { color: #fff; border-color: rgba(255,255,255,.55); }
.dchips { display: flex; gap: 8px; overflow-x: auto; padding: 2px 2px 12px;
          scrollbar-width: none; }
.dchips::-webkit-scrollbar { display: none; }
.dchip { flex: 0 0 auto; padding: 7px 13px; border-radius: 999px;
         font: inherit; font-size: 13.5px; color: var(--ink-2);
         background: var(--paper); border: 1px solid var(--line);
         transition: transform var(--d-press) var(--e-out); }
.dchip:active { transform: scale(var(--press-btn)); }
.dchip.on { background: var(--ink); color: var(--paper);
            border-color: var(--ink); }
.cupb { flex: 0 0 auto; width: 36px; height: 36px; border-radius: 50%;
        border: 1px solid var(--line); background: var(--paper);
        display: flex; align-items: center; justify-content: center;
        transition: transform var(--d-press) var(--e-out); }
.cupb:active { transform: scale(var(--press-ico)); }
.cupb svg { width: 18px; height: 18px; stroke: var(--ink-2);
            stroke-width: 1.7; fill: none; stroke-linecap: round; }
.posrow { display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
          margin-bottom: 8px; }
.posrow input { width: 100%; border: 1px solid var(--line);
                border-radius: var(--r-sm); padding: 10px 12px;
                font: inherit; font-size: 15px; background: var(--ground);
                color: var(--ink); }
.cupta { width: 100%; border: 1px solid var(--line);
         border-radius: var(--r-sm); padding: 10px 12px; font: inherit;
         font-size: 15px; line-height: 1.5; background: var(--ground);
         color: var(--ink); resize: none; margin-bottom: 14px; }
.cupfine { font-size: 12px; color: var(--muted); text-align: center;
           margin: 10px 0 0; }
.mcoffee { display: inline-flex; align-items: center; gap: 6px;
           font-size: 12.5px; font-weight: 600; color: var(--ink-2);
           background: var(--ground); border: 1px solid var(--line);
           border-radius: 999px; padding: 4px 10px; margin: 8px 0 2px;
           font-family: var(--sans); }
.mcoffee svg { width: 14px; height: 14px; stroke: var(--ember);
               stroke-width: 1.8; fill: none; stroke-linecap: round; }
.pworkcup { display: flex; align-items: center; justify-content: center;
            gap: 8px; margin-top: 12px; }
.pworkcup svg { width: 18px; height: 18px; stroke: currentColor;
                stroke-width: 1.7; fill: none; stroke-linecap: round; }
.pcaddt { display: inline-block; margin-top: 6px; font: inherit;
          font-size: 13px; color: #fff; background: rgba(255,255,255,.14);
          border: 1px dashed rgba(255,255,255,.5); border-radius: 999px;
          padding: 5px 12px; }
.pcaddt.dark { color: var(--ink-2); background: var(--paper);
               border-color: var(--line); margin-top: 8px; }

/* ------------------------------------------------------------- billing
   The billing year, native (was a link off to the booking site, and to
   the wrong tab). Own `bil` prefix: `.bk*` belongs to bookings and `.w*`
   to the wallet, and this is neither. Every curve and press scale is a
   token from motion.css. */

.bilyr {
  background: var(--ink);
  color: var(--cream);
  border-radius: var(--r-lg);
  padding: 17px 17px 15px;
  margin: 14px 0 10px;
}
.bilyr small {
  display: block;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: #c8ab74;
}
.bilyr > b {
  display: block;
  font-family: var(--serif);
  font-size: 33px;
  line-height: 1.05;
  margin: 7px 0 2px;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.bilyr p { margin: 0; font-size: 12.5px; color: #b6b2a5; line-height: 1.5; }
.bilrule {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  margin-top: 12px;
  padding-top: 11px;
  border-top: 1px solid rgba(244, 240, 231, .14);
  font-size: 12px;
  color: #d8d4c8;
  font-variant-numeric: tabular-nums;
}
.bilrule b { color: var(--cream); font-weight: 600; }
.bilrule.quiet { border-top-color: transparent; padding-top: 0; margin-top: 5px; }

.bilacts { display: flex; gap: 8px; }
.bilacts .btn { flex: 1; }
.bilnote { margin: 9px 2px 4px; font-size: 11.5px; line-height: 1.5; }

.bilchips { display: flex; gap: 7px; overflow-x: auto; padding: 12px 0 2px; }
.bilchip {
  flex: none;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--paper);
  color: var(--ink-2);
  white-space: nowrap;
  transition: background var(--d-tap) var(--e-inout),
              color var(--d-tap) var(--e-inout),
              transform var(--d-press) var(--e-out);
}
.bilchip.on {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--cream);
  font-weight: 600;
}
.bilchip:active { transform: scale(var(--press-btn)); }

.bilmon { margin-top: 20px; }
.bilmh { display: flex; align-items: baseline; gap: 10px; padding: 0 2px 8px; }
.bilmh b {
  font-family: var(--serif);
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -.01em;
}
.bilmh span {
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.bildl {
  margin-left: auto;
  font: inherit;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink-2);
  background: none;
  border: 0;
  padding: 2px 0;
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: transform var(--d-press) var(--e-out);
}
.bildl:active { transform: scale(var(--press-btn)); }

.billist {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
.bilrow {
  display: grid;
  grid-template-columns: 38px 1fr auto;
  gap: 0 12px;
  align-items: center;
  padding: 13px 14px;
  border-bottom: 1px solid var(--line-soft);
  color: inherit;
  text-decoration: none;
  transition: background var(--d-tap) var(--e-inout);
}
.bilrow:last-child { border-bottom: 0; }
a.bilrow:active { background: var(--line-soft); }

.bildt {
  text-align: center;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .06em;
  color: var(--muted);
  line-height: 1.25;
}
.bildt b {
  display: block;
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.biltx b { display: block; font-size: 14.5px; font-weight: 600; letter-spacing: -.005em; }
.biltx small { display: block; font-size: 12px; color: var(--muted); margin-top: 1px; }
.bilamt { text-align: right; }
.bilamt b { display: block; font-size: 14.5px; font-weight: 600; font-variant-numeric: tabular-nums; }

.bilpill {
  display: inline-block;
  margin-top: 3px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
}
.bilpill.paid { background: #e7f1eb; color: var(--good); }
.bilpill.due { background: #fbf0e2; color: var(--warn); }
.bilpill.overdue { background: #f7e3de; color: var(--ember); }

/* The bookkeeper card on Billing. `bkcard` only adds spacing to `.card`;
   everything else it wears is the card it already is. */
.bkcard { margin-top: 16px; }
/* Inside a sheet the toggle row sits directly above the primary button;
   without this it reads as part of it. */
.sheet .ptogrow { margin: 4px 0 14px; }
.bkcard > b { font-size: 15.5px; font-weight: 600; letter-spacing: -.005em; }

/* ------------------------------------------------- R10: the open Floor
   The Lobby's front page: the masthead pair, the building interleave's
   tag, and the edition's end card in the house night green. */
.lbmast { display: flex; align-items: center; justify-content: space-between;
  gap: 12px; }
.lbshare { display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid var(--line); border-radius: 999px; background: #fff;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  padding: 6px 13px; flex: 0 0 auto; }
.lbshare svg { width: 14px; height: 14px; fill: none; stroke: currentColor;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.lbshare:active { transform: scale(.97); }
.lbed { margin-top: 4px; }
.lbbld .pmedia { position: relative; }
.lbtag { position: absolute; z-index: 1; top: 12px; left: 12px;
  background: rgba(255,255,255,.92); border-radius: 999px;
  font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase;
  font-weight: 700; color: var(--ink-2); padding: 4px 10px; }
.lbend { background: var(--night, #12241f); color: #f6efdd;
  border-radius: var(--r-lg, 20px); padding: 24px 18px; text-align: center;
  margin-bottom: 14px; }
.lbend h3 { font-family: var(--serif); font-weight: 600; font-size: 20px;
  margin: 0 0 6px; }
.lbend p { font-size: 13.5px; color: rgba(246,239,221,.78);
  margin: 0 0 14px; line-height: 1.5; }
.lbend .btn.gold { border: 0; }
.lbend-ghost { display: block; margin-top: 9px; padding: 12px 16px;
  border: 1px solid rgba(246,239,221,.35); border-radius: 12px;
  color: #f6efdd; font-size: 15px; font-weight: 600; text-align: center;
  text-decoration: none; }
.lbrow { display: block; width: 100%; text-align: left; color: inherit;
  padding: 14px 16px; }
.lbrow b { font-size: 14.5px; }
.lbrow span { display: block; color: var(--muted); font-size: 12.5px;
  margin-top: 3px; }
/* Who-can-message-you options: stacked rows, the on-state in ink like
   every made choice in the app. */
.scopeopt { display: block; width: 100%; text-align: left;
  border: 1px solid var(--line); background: var(--paper);
  border-radius: 14px; padding: 13px 16px; font: inherit;
  color: inherit; }
.scopeopt + .scopeopt { margin-top: 8px; }
.scopeopt b { display: block; font-size: 15px; }
.scopeopt small { display: block; font-size: 12.5px; color: var(--muted);
  margin-top: 2px; }
.scopeopt.on { background: var(--ink); border-color: var(--ink);
  color: var(--cream); }
.scopeopt.on small { color: rgba(244,240,231,.72); }
.scopeopt:active { transform: scale(.985); }
/* ------------------------------------------- From the House (offers).
   One card, first slot of Today. The card swipes away (wire() owns the
   gesture; transform/opacity only, snap-back on --e-snap, exit on
   --e-exit); the sheet's dashed box is the redemption: a name a barista
   can read across a counter. */
.hocard { padding: 0; overflow: hidden; touch-action: pan-y; }
.hophoto { width: 100%; aspect-ratio: 16 / 10; object-fit: cover;
           display: block; }
.hophoto.sheetp { border-radius: var(--r-md); aspect-ratio: 16 / 9;
                  margin-bottom: 14px; }
.hobody { padding: 16px 18px 18px; }
.hotag { font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
         text-transform: uppercase; color: var(--muted); }
.hohead { font-family: var(--serif); font-weight: 400; font-size: 22px;
          letter-spacing: -.2px; margin: 8px 0 0; }
.holine { font-size: 14px; line-height: 1.55; color: var(--muted);
          margin: 8px 0 0; }
.horow { display: flex; align-items: center; gap: 10px; margin-top: 14px; }
.hoends { margin-left: auto; font-size: 12.5px; color: var(--muted); }
.hodesk { border: 1.5px dashed var(--line); border-radius: var(--r-md);
          padding: 16px 18px; text-align: center; margin: 14px 0; }
.hodesk .who { font-family: var(--serif); font-size: 26px;
               letter-spacing: -.2px; }
.hodesk .what { font-size: 13px; color: var(--muted); margin-top: 4px; }
.hoterms { font-size: 12.5px; line-height: 1.6; color: var(--muted);
           border-top: 1px solid var(--line-soft); padding-top: 12px;
           margin: 14px 0 0; }

/* -------------------------------------------- R10: the join ceremony
   Three questions before the floor, one per screen; the same grid and
   chips serve the Today industry sheet. */
.jnwrap { padding-top: 9vh; }
.jnstep { font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--muted); font-weight: 700; margin: 0 0 10px; }
.jngrid { display: grid; grid-template-columns: 1fr 1fr; gap: 9px;
  margin-bottom: 14px; }
.jnfield { border: 1px solid var(--line); background: var(--paper);
  border-radius: 13px; padding: 13px 8px; font: inherit; font-size: 13px;
  font-weight: 600; color: inherit; text-align: center; }
.jnfield.on { background: var(--ink); color: var(--cream);
  border-color: var(--ink); }
.jnchips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.jnchip { border: 1px solid var(--line); background: var(--paper);
  border-radius: 999px; padding: 8px 14px; font: inherit; font-size: 13.5px;
  font-weight: 600; color: inherit; }
.jnchip.on { background: var(--ink); color: var(--cream);
  border-color: var(--ink); }
.jnlater { display: block; margin: 12px auto 0; border: 0; background: none;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--muted);
  text-decoration: underline; text-underline-offset: 3px; }
.jndots { display: flex; gap: 6px; justify-content: center;
  padding: 22px 0 40px; }
.jndots i { width: 6px; height: 6px; border-radius: 50%;
  background: #d4d0c4; }
.jndots i.on { background: var(--ink); }
.jnfield:active, .jnchip:active { transform: scale(.97); }
@media (prefers-reduced-motion: reduce) {
  .jnfield:active, .jnchip:active { transform: none; }
}
/* The hollow seal: booked at least once (been here, not yet of the
   house). Same family, outline treatment: no cream field, a firmer
   ring, the J at half ink. The solid seal stays the members'. */
.jpseal.jb { background: transparent; border-color: var(--ink);
             border-width: 1px; }
.jpseal.jb svg path { fill: var(--ink); fill-opacity: .45; }
.cr-nm .jpseal.jb { border-color: rgba(255,255,255,.6); }
.cr-nm .jpseal.jb svg path { fill: #fff; fill-opacity: .6; }


/* ---------------------------------------------------- your page (R11)
   2026-08-25: the You tab is a page now, not a page plus a drawer. The
   header carries the name and three doors (new post, share, settings --
   the composer joined them the same day), and the numbers under
   the photo are a quiet strip, never a scoreboard: serif figures, small
   caps labels, no colour, no growth arrows. */
.mepage .pcard { margin-top: 2px; }
.mehd { display: flex; align-items: center; gap: 10px; padding: 2px 0 12px; }
.mehd { align-items: flex-end; }
.mehd h1 { font-family: var(--serif); font-size: 32px; margin: 0; flex: 1;
           line-height: 1.02; letter-spacing: -.015em; min-width: 0;
           overflow-wrap: anywhere; }
/* The one line that dates you to the building, under your name. */
.mehd h1 span { display: block; font-family: var(--sans); font-size: 13px;
                font-weight: 400; letter-spacing: 0; color: var(--muted);
                line-height: 1.3; margin-top: 5px; }
.mehb { flex: none; width: 38px; height: 38px; border-radius: 50%; border: 0;
        background: var(--paper); color: var(--ink); display: grid;
        place-items: center; box-shadow: var(--shadow);
        transition: transform var(--d-tap) var(--e-out); }
.mehb:active { transform: scale(var(--press-ico)); }
.mehb svg { width: 19px; height: 19px; fill: none; stroke: currentColor;
            stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* Three numbers on one line. A bordered three column card with rules
   between the figures is a leaderboard whatever its caption says. */
.meline { display: flex; align-items: center; gap: 0; margin: 13px 2px 0;
          font-size: 13.5px; color: var(--muted); }
.meline > * { border: 0; background: none; padding: 6px 0; font: inherit;
              color: inherit; transition: opacity var(--d-tap) var(--e-out); }
.meline > * + *::before { content: "\00b7"; opacity: .45; padding: 0 9px; }
.meline button:active { opacity: .5; }
.meline b { font-weight: 600; color: var(--ink);
            font-variant-numeric: tabular-nums; }
.mefine { margin: 8px 4px 0; font-size: 12.5px; color: var(--muted);
          line-height: 1.4; }
/* The house rule, at the foot, where a house rule belongs. */
.mefoot { margin: 24px 10px 4px; text-align: center; line-height: 1.5; }

/* The page's own headings. This page and a member's page have a voice
   the rest of the app does not: they are about a person, not a list of
   controls, so the seams are set in the serif rather than in the tiny
   grey caps that were fighting the tiny grey caps inside the cards. */
.pgsect { margin: 28px 0 11px; }
.pgsect h2 { font-family: var(--serif); font-size: 20px; font-weight: 500;
             letter-spacing: -.01em; text-transform: none;
             color: var(--ink); }
.pgsect .more { font-size: 12.5px; }

/* The composer, as the cell after the last post. */
.ptadd { display: grid; place-items: center; background: var(--ground);
         border: 1px dashed #d8d4c8; color: var(--muted); }
.ptadd svg { width: 26px; height: 26px; fill: none; stroke: currentColor;
             stroke-width: 1.5; stroke-linecap: round; }

/* A followers / following row: the directory's person row, made a
   button, with the button's own chrome removed. */
.flrow { width: 100%; padding: 10px 0; border: 0; background: none;
         color: inherit; font: inherit; text-align: left;
         transition: opacity var(--d-tap) var(--e-out); }
.flrow + .flrow { border-top: 1px solid var(--line-soft); }
.flrow:active { opacity: .6; }
.flwho { flex: 1; min-width: 0; }
.flrow svg { width: 18px; height: 18px; flex: none; color: var(--muted); }

/* ============================================================ mentions
   A mention is the person's name at weight 600 in the house ink, and
   nothing else. It gets NO colour of its own: gold already means money
   in this app and the ember means affection on a post, so a third
   coloured thing would be a third meaning nobody was taught. The
   underline on press is the whole feedback, and it is the same door
   their face is. */
.mn { font: inherit; font-weight: 600; color: var(--ink); border: 0;
      background: none; padding: 0; cursor: pointer;
      border-bottom: 1px solid transparent;
      transition: border-color var(--d-tap) var(--e-out); }
.mn:active { border-bottom-color: var(--line); }

/* The @ picker. Fixed, because it is placed against the field's own
   rect and the keyboard moves that rect on every device differently.
   It grows from the field that opened it (transform-origin), never
   from its own centre, and never from scale(0). */
.mnpick { position: fixed; z-index: 62; background: var(--paper);
          border: 1px solid var(--line); border-radius: var(--r-md);
          box-shadow: var(--shadow-lift); overflow: hidden;
          transform-origin: bottom center;
          transform: translateY(6px) scale(.97); opacity: 0;
          pointer-events: none;
          transition: transform var(--d-tap) var(--e-out),
                      opacity var(--d-tap) var(--e-out); }
.mnpick.in { transform: none; opacity: 1; pointer-events: auto; }
.mnrow { display: flex; gap: 10px; align-items: center; width: 100%;
         border: 0; background: none; padding: 9px 12px; cursor: pointer;
         text-align: left; font: inherit; color: var(--ink);
         transition: transform var(--d-press) var(--e-out),
                     background var(--d-tap) var(--e-out); }
.mnrow + .mnrow { border-top: 1px solid var(--line-soft); }
.mnrow:active { transform: scale(var(--press-row));
                background: var(--ground); }
.mnrow .av { width: 30px; height: 30px; flex: none; }
.mnrow b { display: block; font-size: 13.5px; }
.mnrow span span { font-size: 11.5px; color: var(--muted); }
.mncap { padding: 10px 12px; font-size: 12.5px; color: var(--muted);
         border-top: 1px solid var(--line-soft); }
.mnpick .mncap:first-child { border-top: 0; }

/* ================================================================ FIVE
   The camera, the shutter and the review. Two full-screen layers, and
   BOTH carry an explicit z-index: their children (shutter, close, the
   source chips) carry their own, and a parent without one never makes a
   stacking context, so the camera's chrome punches straight through the
   review that is supposed to be covering it. They sit above the tab bar
   (50) and the Lightbox (55) and below the veil (60) that any sheet or
   confirm rides on. */
.fv-cam, .fv-rev { position: fixed; inset: 0; background: #000;
                   opacity: 0; transform: scale(1.03);
                   transition: opacity var(--d-enter) var(--e-out),
                               transform var(--d-enter) var(--e-out); }
.fv-cam { z-index: 56; }
.fv-rev { z-index: 57; transform: scale(1.01); }
.fv-cam.in, .fv-rev.in { opacity: 1; transform: none; }
.fv-view, .fv-rv { position: absolute; inset: 0; width: 100%;
                   height: 100%; object-fit: cover; background: #0d1211; }
.fv-view.mir { transform: scaleX(-1); }

.fv-x, .fv-flip { position: absolute;
        top: calc(env(safe-area-inset-top, 0px) + 14px);
        width: 36px; height: 36px; border-radius: 999px; border: 0;
        background: rgba(16, 24, 22, .42); -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px); display: flex; align-items: center;
        justify-content: center; padding: 0; z-index: 4;
        transition: transform var(--d-press) var(--e-out); }
.fv-x { left: 14px; }
.fv-flip { right: 14px; }
.fv-x:active, .fv-flip:active { transform: scale(var(--press-ico)); }
.fv-x svg, .fv-flip svg { width: 17px; height: 17px; fill: none;
        stroke: #fff; stroke-width: 1.7; stroke-linecap: round;
        stroke-linejoin: round; }

.fv-clock { position: absolute; left: 0; right: 0;
        top: calc(env(safe-area-inset-top, 0px) + 62px);
        display: flex; align-items: center; justify-content: center;
        gap: 7px; color: #fff; font-size: 13px; font-weight: 700;
        letter-spacing: .04em; font-variant-numeric: tabular-nums;
        opacity: 0; text-shadow: 0 1px 10px rgba(0, 0, 0, .5);
        transition: opacity var(--d-tap) var(--e-out); }
.fv-clock.in { opacity: 1; }
.fv-clock i { width: 8px; height: 8px; border-radius: 999px;
              background: var(--ember); flex: none; }

.fv-line, .fv-hint { position: absolute; left: 22px; right: 22px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 196px);
        text-align: center; font-size: 12.5px; line-height: 1.5;
        color: rgba(255, 255, 255, .82);
        text-shadow: 0 1px 12px rgba(0, 0, 0, .55);
        transition: opacity var(--d-tap) var(--e-out); }
.fv-hint { color: #fff; font-weight: 600; opacity: 0; }
.fv-hint.in { opacity: 1; }

.fv-src { position: absolute; left: 0; right: 0;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 152px);
        display: flex; gap: 6px; justify-content: center; z-index: 4; }
.fv-src button { border: 0; background: rgba(16, 24, 22, .42);
        -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
        color: rgba(255, 255, 255, .72); font: inherit; font-size: 12px;
        font-weight: 600; letter-spacing: .02em; padding: 7px 14px;
        border-radius: 999px;
        transition: transform var(--d-press) var(--e-out),
                    background var(--d-tap) var(--e-out),
                    color var(--d-tap) var(--e-out); }
.fv-src button:active { transform: scale(var(--press-btn)); }
.fv-src button.on { background: #fff; color: var(--ink); }

/* The shutter. The ring is a CLOCK, not a motion: it fills linearly,
   because easing it would be a lie about how much time is left, and it
   is driven by one animation frame loop off performance.now() rather
   than a keyframe, so it can never drift away from the file being
   written. */
.fv-shut { position: absolute; left: 50%; margin-left: -42px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 46px);
        width: 84px; height: 84px; z-index: 5; touch-action: none;
        -webkit-tap-highlight-color: transparent; }
.fv-ring { position: absolute; inset: 0; transform: rotate(-90deg); }
.fv-ring circle { fill: none; stroke-linecap: round; }
.fv-ring .trk { stroke: rgba(255, 255, 255, .28); stroke-width: 4; }
.fv-ring .arc { stroke: var(--ember); stroke-width: 4;
                stroke-dasharray: 201.06; stroke-dashoffset: 201.06; }
.fv-core { position: absolute; inset: 12px; border-radius: 999px;
        background: #fff; box-shadow: 0 2px 14px rgba(0, 0, 0, .35);
        transition: transform var(--d-press) var(--e-out),
                    background var(--d-tap) var(--e-out); }
.fv-shut.down .fv-core { transform: scale(.86); background: #f2ece4; }
.fv-shut.snap .fv-core { transform: none;
        transition: transform var(--d-tap) var(--e-snap); }

/* The window over a longer recording: you choose the five seconds, we
   never keep the first five and call it a trim. */
.fv-trim { position: absolute; left: 16px; right: 16px;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 200px); z-index: 4; }
.fv-tstrip { position: relative; height: 44px; border-radius: 10px;
        background: rgba(16, 24, 22, .5); -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px); touch-action: none; overflow: hidden; }
.fv-twin { position: absolute; top: 0; bottom: 0; left: 0; width: 30%;
        border: 2px solid #fff; border-radius: 10px;
        background: rgba(255, 255, 255, .14); }
.fv-tnote { margin: 7px 0 0; text-align: center; font-size: 11.5px;
        color: rgba(255, 255, 255, .72); }

/* Review. */
.fv-sheet { position: absolute; left: 0; right: 0; bottom: 0;
        padding: 18px 16px calc(env(safe-area-inset-bottom, 0px) + 18px);
        background: linear-gradient(to top, rgba(9, 12, 11, .95),
                    rgba(9, 12, 11, .78) 62%, rgba(9, 12, 11, 0));
        color: #fff; }
.fv-edges { margin: 0 0 10px; font-size: 12.5px;
            color: rgba(255, 255, 255, .74); }
.fv-cap { width: 100%; border: 0;
        border-bottom: 1px solid rgba(255, 255, 255, .26);
        background: none; color: #fff; font: inherit; font-size: 15px;
        padding: 6px 0 9px; outline: none; resize: none;
        transition: border-color var(--d-tap) var(--e-out); }
.fv-cap::placeholder { color: rgba(255, 255, 255, .45); }
.fv-cap:focus { border-bottom-color: var(--accent); }
.fv-chips { display: flex; gap: 7px; margin: 13px 0 0; flex-wrap: wrap; }
.fv-chip { border: 1px solid rgba(255, 255, 255, .3); background: none;
        color: #fff; font: inherit; font-size: 12.5px; padding: 6px 11px;
        border-radius: 999px;
        transition: transform var(--d-press) var(--e-out),
                    background var(--d-tap) var(--e-out),
                    border-color var(--d-tap) var(--e-out); }
.fv-chip:active { transform: scale(var(--press-btn)); }
.fv-chip.on { background: #fff; color: var(--ink); border-color: #fff; }
.fv-mute { display: flex; align-items: center; gap: 9px; margin: 14px 0 0;
        width: 100%; border: 0; background: none; color: #fff;
        font: inherit; font-size: 13.5px; padding: 0;
        transition: transform var(--d-press) var(--e-out); }
.fv-mute:active { transform: scale(var(--press-row)); }
.fv-sw { width: 40px; height: 24px; border-radius: 999px; flex: none;
        background: rgba(255, 255, 255, .24); position: relative;
        transition: background var(--d-tap) var(--e-out); }
.fv-sw::after { content: ""; position: absolute; top: 3px; left: 3px;
        width: 18px; height: 18px; border-radius: 999px; background: #fff;
        transition: transform var(--d-tap) var(--e-out); }
.fv-mute.on .fv-sw { background: var(--good); }
.fv-mute.on .fv-sw::after { transform: translateX(16px); }
.fv-acts { display: flex; gap: 9px; margin: 17px 0 0; }
.fv-btn { flex: 1; border: 0; border-radius: var(--r-md); padding: 14px 12px;
        font: inherit; font-size: 14.5px; font-weight: 600;
        background: var(--accent); color: var(--ink);
        transition: transform var(--d-press) var(--e-out); }
.fv-btn.ghost { flex: 0 0 auto; background: none; color: #fff;
        border: 1px solid rgba(255, 255, 255, .3); font-weight: 500; }
.fv-btn:active { transform: scale(var(--press-btn)); }
.fv-stat { margin: 10px 0 0; text-align: center; font-size: 12.5px;
           color: rgba(255, 255, 255, .74); min-height: 15px; }

/* The door on Making, beside the composer.
   The row owns the bottom margin, not the composer. The composer
   carries margin-bottom:14px for its standalone use, and inside a
   stretch row that margin shortened the pill's box while the shutter
   stretched the full height, so the shutter hung exactly 14px below
   the pill. Fahad spotted it on his phone; measured at 51px vs 65px. */
.vcrow { display: flex; gap: 9px; align-items: stretch;
         margin-bottom: 14px; }
.vcrow .vcomposer { flex: 1; margin-bottom: 0; }
.vfive { flex: none; width: 52px; border: 1px solid var(--line);
        border-radius: var(--r-md); background: var(--paper);
        display: grid; place-items: center;
        transition: transform var(--d-press) var(--e-out),
                    background var(--d-tap) var(--e-out); }
.vfive:active { transform: scale(var(--press-btn));
                background: var(--ground); }
.vfive svg { width: 21px; height: 21px; fill: none; stroke: var(--ink);
             stroke-width: 1.6; stroke-linecap: round;
             stroke-linejoin: round; }

@media (prefers-reduced-motion: reduce) {
  /* The RING still fills: it is information, not decoration. What goes
     is the press scale, the pop, and the fade between screens. */
  .fv-cam, .fv-rev, .fv-core, .fv-src button, .fv-chip, .fv-btn,
  .fv-mute, .mnpick, .mnrow { transition: none; }
}

/* The Five ring: a warm hairline around a face that shot one in the
   last few hours. It is the whole of "blast it" (Fahad's call): the
   floor looks alive, and not one phone buzzes. It fades on its own when
   the server stops listing the handle; there is nothing to dismiss. */
.av.fivering, .vring.fivering { position: relative; }
.av.fivering::after, .vring.fivering::after {
  content: ""; position: absolute; inset: -3px; border-radius: 999px;
  border: 1.5px solid var(--ember); pointer-events: none; }
.vring.fivering::after { inset: -2px; }

/* Desktop. The Floor is one app on every screen, not two, so the
   camera is the same camera; it just stops stretching a phone-shaped
   interface across a monitor. The picture is capped to a column and
   centred, and every control lines up under it. */
@media (min-width: 720px) {
  .fv-view, .fv-rv { left: 50%; right: auto; width: min(520px, 100%);
                     transform: translateX(-50%); }
  .fv-view.mir { transform: translateX(-50%) scaleX(-1); }
  .fv-sheet, .fv-src, .fv-trim, .fv-line, .fv-hint {
    left: 50%; right: auto; width: min(520px, 100%);
    transform: translateX(-50%); }
  .fv-sheet { padding-left: 22px; padding-right: 22px; }
  /* The close and the flip hug the picture, not the monitor. */
  .fv-x { left: calc(50% - min(260px, 50vw) + 14px); }
  .fv-flip { right: calc(50% - min(260px, 50vw) + 14px); }
  .fv-cam::before, .fv-rev::before {
    content: ""; position: absolute; inset: 0; background: #0a0d0c; }
  .fv-view, .fv-rv, .fv-sheet, .fv-src, .fv-trim, .fv-line, .fv-hint,
  .fv-shut, .fv-clock, .fv-x, .fv-flip { z-index: 2; }
  .mnpick { max-width: 520px; }
}

/* ---------------------------------------------- the paper's asks band
   (Sept 1, 2026-08-25). Rows, not cards: an ask is a line of the paper
   with a clock on it, and four of them must not out-shout the stories
   underneath. Press feedback uses the row token like every other full
   width target. */
.askband { padding: 4px 0; }
.askrow { display: flex; align-items: center; gap: 10px; width: 100%;
          text-align: left; background: none; border: 0;
          padding: 11px 14px; border-bottom: 1px solid var(--line-soft);
          transition: transform var(--d-press) var(--e-out); }
.askrow:last-child { border-bottom: 0; }
.askrow:active { transform: scale(var(--press-row)); }
.askbd { flex: 1; min-width: 0; }
.askbd b { display: block; font-weight: 500; font-size: 14.5px;
           color: var(--ink); line-height: 1.35; }
/* .why is styled by its own parents elsewhere, so here it inherits
   ink at 16px and out-shouts the ask itself. Name it explicitly. */
.askbd .why { display: block; margin-top: 2px; font-size: 12.5px;
              color: var(--muted); }
.askcta { flex: 0 0 auto; font-size: 12.5px; color: var(--muted);
          border: 1px solid var(--line); border-radius: 999px;
          padding: 5px 11px; }

/* ---------------------------------------------- the member spotlight
   The house's own voice, so it wears the cream field the house uses
   everywhere else rather than the white of a member's post. The byline
   is not decoration: it is the line that stops a reader mistaking an
   editorial for a member bragging about themselves. */
.card.spot, .card.spotask { background: var(--cream);
                            border-color: transparent; }
.spotbrow { display: block; font-size: 10.5px; letter-spacing: .12em;
            text-transform: uppercase; color: var(--muted);
            font-weight: 600; margin-bottom: 10px; }
.spothd { display: flex; align-items: center; gap: 9px; width: 100%;
          text-align: left; background: none; border: 0; padding: 0;
          transition: transform var(--d-press) var(--e-out); }
.spothd:active { transform: scale(var(--press-btn)); }
.spothd b { font-size: 15.5px; color: var(--ink); }
.spotbd { font-family: var(--serif); font-size: 16.5px; line-height: 1.45;
          color: var(--ink-2); margin: 11px 0 10px; }
.spotby { display: block; font-size: 12.5px; color: var(--muted); }
.card.spotask b { display: block; font-size: 15.5px; color: var(--ink); }
.card.spotask .sub { margin: 3px 0 0; }

/* The featured picture. Inset inside the card's padding rather than
   full bleed: square corners bleeding inside a 20px card radius read as
   a mistake. 4/5 is the portrait ratio this app already uses everywhere
   a person appears, the max-height keeps the first lines of the blurb
   above the fold on a small phone, and the crop sits above centre
   because a face in a hand-held portrait does, and a dead-centre crop
   takes the top of someone's head off. */
/* max-width, never max-height: a height cap fights the aspect-ratio and
   the picture silently becomes landscape on a wide screen, so the crop
   a member approved is not the crop that runs. Capping the WIDTH keeps
   4/5 true on every screen (full width on a phone, a plate on
   desktop). 50% 30% because a face in a hand-held portrait sits above
   centre, and a dead-centre crop takes the top of the head off. */
.spotpic { display: block; width: 100%; max-width: 340px;
           aspect-ratio: 4 / 5; object-fit: cover;
           object-position: 50% 30%; border-radius: 14px;
           background: var(--ground); margin: 0 auto 12px; }

/* No picture is not a degraded card, it is a text feature: bigger type
   and a drop cap, the way a paper runs one. */
.card.spot.nopic .spotbd { font-size: 17.5px; }
.card.spot.nopic .spotbd.cap::first-letter {
  float: left; font-size: 46px; line-height: .82; padding: 4px 7px 0 0;
  font-family: var(--serif); color: var(--ink); }

/* The consent ceremony wraps the REAL card, so the inner card drops its
   shadow rather than stacking two. */
.spotwrap { margin: 12px 0 14px; }
.spotwrap .card.spot { margin: 0; box-shadow: none;
                       background: var(--paper); }
.spotnopic { display: block; margin: 12px auto 0; color: var(--muted);
             font-size: 13.5px; text-decoration: underline;
             text-underline-offset: 3px; }

/* milestones (R10): the 10k rail, the pick card, the choose sheet */
.mspick { display: flex; align-items: center; gap: 13px; width: 100%;
          text-align: left; color: inherit;
          border-color: var(--accent);
          box-shadow: 0 0 0 3px rgba(255,200,56,.14); }
.msc-top { display: flex; align-items: baseline; gap: 10px;
           flex-wrap: wrap; justify-content: space-between;
           margin: 0 0 14px; }
.msc-top b { font-size: 14px; }
.msc-next { font-size: 11.5px; color: var(--muted);
            font-variant-numeric: tabular-nums; white-space: nowrap; }
.msrail { overflow-x: auto; -webkit-overflow-scrolling: touch;
          scrollbar-width: none; margin: 0 -4px; padding: 2px 4px; }
.msrail::-webkit-scrollbar { display: none; }
/* the road owns the geometry: it grows with its stops, so the track,
   the gold fill and the markers all measure against the same width */
.msroad { position: relative; display: flex; width: max-content;
          min-width: 100%; }
.msroad::before { content: ""; position: absolute; top: 10px; left: 0;
                  right: 0; height: 2px; border-radius: 999px;
                  background: var(--line-soft); }
.msfill { position: absolute; top: 10px; left: 0; height: 2px;
          border-radius: 999px; background: var(--accent); }
.msd { flex: 1 0 68px; text-align: center; position: relative;
       padding-top: 24px; }
.msd i { position: absolute; top: 4px; left: 50%;
         transform: translateX(-50%); width: 14px; height: 14px;
         border-radius: 50%; border: 2px solid var(--line);
         background: var(--paper); z-index: 1;
         display: grid; place-items: center; }
.msd i svg { width: 9px; height: 9px; display: block;
             color: var(--accent-ink); }
.msd.on i { border-color: var(--accent); background: var(--accent); }
.msd.wait i { box-shadow: 0 0 0 3px rgba(255,200,56,.28); }
.msd.ks i { background: var(--night); border-color: var(--night); }
.msd.ks.on i svg { color: var(--accent); }
.msd span { display: block; font-size: 11px; font-weight: 700;
            font-variant-numeric: tabular-nums; }
.msd small { display: block; font-size: 9.5px; color: var(--muted);
             line-height: 1.25; padding: 0 2px; margin-top: 1px;
             min-height: 12px; }
.msd small.gold { color: var(--warn); font-weight: 600; }
.msopts { display: flex; flex-direction: column; gap: 8px; }
.msopt { display: block; width: 100%; text-align: left;
         background: var(--paper); border: 1px solid var(--line);
         border-radius: var(--r-md); padding: 12px 14px; color: inherit; }
.msopt:active { border-color: var(--accent); }
.msopt b { display: block; font-size: 14.5px; }
.msopt span { display: block; font-size: 12.5px; color: var(--muted);
              margin-top: 2px; }
.wval.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
             font-size: 12.5px; letter-spacing: .04em; }
/* ------------------------------------------- the Circle signup (R1) */
/* Two steps, six fields. The hint beside a label is the quiet part of
   the design: it says "we already knew this", which is what stops a
   prefilled box reading as something the person has to check. */
.csg h3 { display: flex; align-items: center; gap: 8px; }
.csg .csg-p { margin: 0 0 16px; font-size: 14.5px; line-height: 1.5;
  color: var(--muted); }
.csg .field { margin-bottom: 12px; }
.csg .field label { display: flex; justify-content: space-between;
  align-items: baseline; gap: 8px; }
.csg-hint { font-style: normal; font-size: 11.5px; color: var(--good, #3C8460);
  font-weight: 600; }
.csg-err { display: none; font-size: 12px; color: #C0503C; margin-top: 5px; }
.csg .field.bad input { border-color: #C0503C; }
.csg .field.bad .csg-err { display: block; }
.csg-two { display: flex; gap: 9px; }
.csg-two .field:first-child { flex: 1; }
.csg-two .field:last-child { flex: 0 0 86px; }

.csg-back { background: none; border: 0; padding: 0 2px 0 0; cursor: pointer;
  font-size: 22px; line-height: 1; color: var(--muted); }

.csg-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.csg-chip { border: 1px solid var(--line, #E2DAC6); background: transparent;
  border-radius: 99px; padding: 7px 12px; font: inherit; font-size: 13px;
  color: inherit; cursor: pointer; }
/* Instant, not animated: this fires many times a minute while somebody
   makes up their mind, and motion on it would read as lag. */
.csg-chip.on { background: var(--ink, #1E2A33); border-color: var(--ink, #1E2A33);
  color: #F6F0E2; font-weight: 600; }
.csg-chip:active { transform: scale(0.97); }

.csg-opt { margin: 16px 0 6px; font-size: 11px; letter-spacing: .09em;
  text-transform: uppercase; color: var(--muted); font-weight: 700; }
.csg-consent { display: flex; gap: 10px; align-items: flex-start;
  border: 1px solid var(--line, #E2DAC6); border-radius: 12px;
  padding: 12px 13px; margin-bottom: 16px; cursor: pointer; }
.csg-consent input { margin: 2px 0 0; width: 19px; height: 19px;
  flex: 0 0 auto; accent-color: var(--ink, #1E2A33); }
.csg-consent b { display: block; font-size: 14px; line-height: 1.4;
  font-weight: 600; }
.csg-consent i { display: block; font-style: normal; font-size: 12px;
  line-height: 1.4; color: var(--muted); margin-top: 4px; }
.csg-fine { margin: 10px 0 0; font-size: 12px; color: var(--muted);
  text-align: center; line-height: 1.4; }

/* the one-time card for members who joined before the form existed */
.csg-card { margin-bottom: 14px; }
.csg-seal { width: 26px; height: 26px; border-radius: 50%;
  background: var(--ink, #1E2A33); color: #F6F0E2; display: flex;
  align-items: center; justify-content: center; font-weight: 600;
  font-size: 14px; margin-bottom: 10px; }
.csg-card h3 { margin: 0 0 5px; font-size: 18px; }
.csg-card p { margin: 0 0 13px; font-size: 14px; line-height: 1.45;
  color: var(--muted); }
.csg-acts { display: flex; gap: 10px; align-items: center; }
.csg-acts .btn { flex: 1; }
.csg-not { background: none; border: 0; font: inherit; font-size: 13.5px;
  color: var(--muted); padding: 10px 6px; cursor: pointer; }

@media (prefers-reduced-motion: reduce) {
  .csg-chip:active { transform: none; }
}

/* A locked field is not a disabled one: it must still read as a fact
   about their account, not as a box that failed. Same type, quieter
   ground, no focus ring, cursor says "not yours to type". */
.csg .field input[readonly] {
  background: rgba(0, 0, 0, .035);
  color: var(--muted);
  cursor: default;
}
.csg .field input[readonly]:focus { outline: none; border-color: var(--line, #E2DAC6); }

/* --------------------------------------------- team accounts (R1) */
/* The pool card is the dark one: it is the company's money, and it
   should not look like the member's own balance card. */
.tmpool { background: var(--ink, #1E2A33); color: #F6F0E2;
  border-radius: 18px; padding: 15px 16px 16px; margin-bottom: 12px; }
.tmlbl { font-size: 10.5px; letter-spacing: .14em; text-transform: uppercase;
  opacity: .62; margin-bottom: 8px; }
.tmbig { font-family: var(--serif, Georgia), serif; font-size: 33px;
  line-height: 1; font-weight: 600; }
.tmbig small { font-size: 14px; font-weight: 400; opacity: .7;
  margin-left: 5px; font-family: inherit; }
.tmbar { height: 5px; border-radius: 3px; background: rgba(246,240,226,.15);
  margin-top: 10px; display: flex; overflow: hidden; }
.tmbar span { display: block; height: 100%; }
.tmwho { margin-top: 11px; border-top: 1px solid rgba(246,240,226,.16);
  padding-top: 9px; }
.tmr { display: flex; font-size: 12.5px; padding: 3px 0; }
.tmr b { margin-left: auto; font-variant-numeric: tabular-nums; }

.tmmine { border: 1px solid var(--line, #E2DAC6); border-radius: 14px;
  padding: 12px 14px; margin-bottom: 12px; }
.tmmine .t { font-size: 10.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--muted); font-weight: 700; }
.tmmine .v { font-family: var(--serif, Georgia), serif; font-size: 24px;
  color: var(--ink, #1E2A33); font-weight: 600; margin-top: 3px; }
.tmmine p { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45;
  color: var(--muted); }
.tmlock { color: #8A6110 !important; }

/* The lead's switch. Instant on tap, then confirmed by the server:
   it fires often while somebody sets up a team and any animation on it
   would read as lag. */
.tmsw { width: 40px; height: 23px; border-radius: 99px; background: #DAD3C2;
  position: relative; flex: 0 0 auto; border: 0; padding: 0; margin-right: 8px;
  cursor: pointer; }
.tmsw:after { content: ""; position: absolute; top: 2.5px; left: 2.5px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff;
  box-shadow: 0 1px 2px rgba(0,0,0,.25); }
.tmsw.on { background: #3C8460; }
.tmsw.on:after { left: 19.5px; }
.tmsw:focus-visible { outline: 2px solid var(--ink, #1E2A33); outline-offset: 2px; }

/* THE ROOM SCREEN INTRO. Three photographs of the real wall, shown once to
   a member with a screened room and nothing on it yet.

   The pictures do the selling, so the card keeps everything else quiet: no
   shadow, no second border, the same paper the other cards sit on. Curves
   and durations come from motion.css; nothing is typed here. */
.scrintro .shots {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
  margin: 12px 0 4px; }
.scrintro .shots figure { margin: 0; min-width: 0; }
.scrintro .shots img {
  display: block; width: 100%; height: auto; border-radius: 8px;
  background: var(--line, #e4e2da); }
.scrintro .shots figcaption {
  font-size: 11px; line-height: 1.3; color: var(--muted, #6e6d68);
  margin-top: 6px; }
.scrintro p { margin: 4px 0 0; }
.scrintro .btn.wide { margin-top: 12px; }
/* On a narrow phone three captions stack into six lines and the card grows
   taller than the hero above it. The pictures still read at this size; the
   captions are the part that can go. */
@media (max-width: 380px) {
  .scrintro .shots figcaption { display: none; }
  .scrintro .shots { margin-bottom: 8px; }
}

/* HOW THE WATCHED CALENDAR WORKS. Five cards in a sheet, opened from a
   quiet line. Curves and durations come from motion.css. */
.cfx-line {
  display: flex; align-items: center; justify-content: space-between;
  width: 100%; gap: 8px; background: none; border: 0; padding: 8px 2px;
  font: inherit; font-size: 13.5px; color: var(--muted, #6e6d68);
  cursor: pointer; text-align: left;
  transition: transform var(--d-press) var(--e-out); }
.cfx-line:active { transform: scale(var(--press-row, .985)); }
.cfx-line svg { flex: none; opacity: .6; }
.cfx-bars { display: flex; gap: 5px; margin: 2px 0 16px; }
.cfx-bar {
  flex: 1; height: 3px; border-radius: 2px;
  background: rgba(30, 42, 51, .14);
  transition: background var(--d-tap) var(--e-out); }
.cfx-bar.on { background: var(--ink, #1E2A33); }
.cfx-step {
  font-size: 11px; letter-spacing: .14em; text-transform: uppercase;
  color: var(--muted, #6e6d68); margin-bottom: 6px; }
#cfx h3 { margin: 0 0 8px; }
#cfx p { margin: 0; line-height: 1.55; }
/* Two frames on the last card, because "the room already knows" is the one
   claim a sentence cannot make. */
.cfx-shots { display: grid; grid-template-columns: 1fr 1fr; gap: 6px;
  margin-top: 14px; }
.cfx-shots img {
  display: block; width: 100%; height: auto; border-radius: 8px;
  background: var(--line, #e4e2da); }
.cfx-foot { display: flex; gap: 8px; margin-top: 18px; }
.cfx-foot .btn.wide { flex: 1; }
