@layer components {
  /* ── Stay shell ──
     One page architecturally for every stay/* URL. Cork desk wraps the
     beige board (the prep page); summoned cards (Profile, Logistics)
     layer onto the board itself — they're NOT floating modals. They
     scroll with the rest of the page. The clip is absolute on the
     board too; it's hidden when no card is summoned and slides into
     place when one is. */

  /* The shell paints cork on the body and html roots so the texture
     covers the entire viewport edge-to-edge regardless of content
     height, scroll bounce, or pull-to-refresh gestures. */
  html:has(.stay-shell),
  body:has(.stay-shell) {
    background-color: #fff;
  }

  .stay-shell {
    position: relative;
    min-height: 100vh;
    background-color: #fff;
    padding: 92px var(--space-6) var(--space-9);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-start;
  }

  /* Landscape backdrop — inline SVG rendered as the first child of the
     shell. Fixed to the viewport so the board scrolls in front of a
     stable scene. Pointer-events disabled so it never intercepts clicks. */
  .stay-landscape {
    position: fixed;
    inset: 0;
    width: 100vw;
    height: 100vh;
    z-index: 0;
    pointer-events: none;
  }

  /* ── Stay nav bar ──
     Sits in the cork space above the clip. The gap between nav and
     clip is the nav-bar clearance — the modal anchor floor is the
     board top, never higher. */
  .stay-nav {
    position: absolute;
    top: 0; left: 0; right: 0;
    height: 64px;
    /* Right padding reserves space for the fixed avatar (36px wide
       sitting at right: 32px) so the +new-gathering CTA never slides
       under it. */
    padding: 0 88px 0 32px;
    display: flex;
    align-items: center;
    gap: 24px;
    z-index: 80;
    pointer-events: auto;
    transition: opacity 220ms ease;
  }
  .stay-nav--hidden {
    opacity: 0;
    pointer-events: none;
  }
  .stay-nav-brand {
    font-family: var(--display);
    font-style: normal;
    font-size: 18px;
    font-weight: var(--weight-medium);
    color: var(--ink);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    text-decoration: none;
  }
  .stay-nav-brand:hover { color: var(--ink); text-decoration: none; }
  /* Wordmark fades on scroll past the nav-bar threshold. The avatar
     stays put because it's a separate element. */
  .stay-nav-brand {
    transition: opacity 220ms ease, transform 220ms ease;
  }
  .stay-nav-brand.scrolled {
    opacity: 0;
    transform: translateY(-6px);
    pointer-events: none;
  }
  .stay-nav-links {
    display: flex;
    gap: 18px;
    flex: 1;
  }
  .stay-nav-link {
    font-size: 13px;
    color: var(--ink-soft);
    text-decoration: none;
    padding: 4px 2px;
  }
  .stay-nav-link:hover { color: var(--ink); text-decoration: underline; }
  .stay-nav-avatar {
    position: relative;
    width: 36px; height: 36px;
    border-radius: 50%;
    overflow: hidden;
    background: var(--paper-warm);
    border: 1px solid rgba(0,0,0,0.18);
    display: flex; align-items: center; justify-content: center;
    text-decoration: none;
    color: var(--ink);
    font-size: 11px;
    letter-spacing: 0.06em;
    font-weight: var(--weight-semibold);
    box-shadow: 0 2px 4px rgba(0,0,0,0.15);
    transition: transform .12s ease;
  }
  /* Pin the photo to the container so flex-item intrinsic sizing can't shrink it. */
  .stay-nav-avatar-img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
  }
  .stay-nav-avatar:hover { transform: translateY(-1px); text-decoration: none; }
  /* The avatar is now a <button> — reset native chrome. */
  button.stay-nav-avatar {
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    font: inherit;
  }
  button.stay-nav-avatar:focus { outline: none; }
  button.stay-nav-avatar:focus-visible {
    outline: 2px solid rgba(255,255,255,0.7);
    outline-offset: 2px;
  }

  /* ── Avatar dropdown ──
     Wrap is detached from the flex nav and pinned to the top-right of
     the viewport so the avatar remains visible as the page scrolls.
     The dropdown still positions absolutely against this wrap. */
  .stay-nav-avatar-wrap {
    position: fixed;
    top: 14px;
    right: 32px;
    z-index: 90;
  }
  /* Pending-requests count on the avatar (the .stay-nav-avatar button has
     overflow:hidden, so the badge lives in the wrap and overhangs the
     corner). It steps aside once the menu opens — the count then shows on
     the Manage entry inside the menu. */
  .stay-nav-avatar-badge {
    position: absolute;
    top: -3px;
    right: -3px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    border-radius: 999px;
    background: var(--pink);
    color: #fff;
    font-family: var(--sans);
    font-size: 10px;
    font-weight: var(--weight-bold);
    line-height: 1;
    border: 1.5px solid #fff;
    z-index: 91;
    pointer-events: none;
  }
  .stay-nav-avatar-wrap:has(.avatar-menu.open) .stay-nav-avatar-badge { display: none; }
  /* The pending-count badges (avatar, Manage entry, manage tabs) are always
     rendered so the cabin-timeline controller can keep them in sync without a
     refresh; a zero count just hides them. */
  [data-pending][hidden] { display: none; }

  /* Avatar dropdown — a stack of glass pill buttons that drops below
     the avatar when open. No paper card; each item is its own pill,
     same family as .btn-glass. */
  .avatar-menu {
    position: absolute;
    top: 48px;
    right: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
    padding: 0;
    background: transparent;
    border: none;
    box-shadow: none;
    opacity: 0;
    transform: translateY(-4px);
    pointer-events: none;
    transition: opacity 140ms ease, transform 140ms ease;
    z-index: 90;
  }
  .avatar-menu.open {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
  }
  /* Brand pass: black-outline pills over white, filling black on hover.
     Sign-out is the one filled-black entry. */
  .avatar-menu-item {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    height: 36px;
    padding: 0 18px;
    font-family: var(--sans);
    font-size: 12px;
    font-weight: var(--weight-bold);
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink);
    background: #fff;
    border: 1px solid var(--ink);
    border-radius: 999px;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease;
  }
  .avatar-menu-item--signout { background: #000; color: #fff; border-color: #fff; }
  /* Sign-out renders via button_to, so it's a <button> wrapped in a
     <form>. display:contents lets the button take part in the menu's
     flex layout as if the form weren't there. */
  .avatar-menu form { display: contents; margin: 0; }
  .avatar-menu-item:hover {
    background: var(--ink);
    color: #fff;
    text-decoration: none;
  }
  .avatar-menu-item--quiet { opacity: 0.92; }
  /* Pending-requests count, sitting on the Manage pill. */
  .avatar-menu-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    box-sizing: border-box;
    border-radius: 999px;
    background: var(--pink);
    color: #fff;
    font-size: 11px;
    font-weight: var(--weight-bold);
    line-height: 1;
  }
  .avatar-menu-icon {
    width: 14px;
    height: 14px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    flex-shrink: 0;
  }

  /* "+ New" create menu in the nav — same pill shape + dropdown as the
     avatar menu, but its items read as a paired set with the glass "+ New"
     trigger: white pill, olive outline + label, filling olive on hover. */
  .create-menu-wrap { position: relative; }
  .create-menu-trigger { cursor: pointer; }
  .create-menu.avatar-menu { top: 40px; }
  .create-menu-item {
    background: #fff;
    color: var(--ink);
    border: 1px solid var(--ink);
  }
  .create-menu-item:hover {
    background: var(--ink);
    color: #fff;
  }

  /* The beige board IS the prep page. Padding-top is 0 — the card and
     prep content live at the very top of the board, sharing the same
     baseline. Internal breathing room comes from .stay-board-content. */
  /* ── Wood tray ──
     Thin masonite backer wrapping the paper board so the clipboard
     metaphor reads beyond just the metal clip. Tray is sized just
     larger than the board, so on wide viewports only a hairline of
     wood is visible past the paper edge. On narrow viewports the tray
     fills the available width and the wood frame absorbs whatever gap
     existed between paper and shell padding. */
  /* Glass return button — sits centered on the landscape below the
     tray, takes the member back to the lodge. Uses the shared
     .btn-glass shape so it matches other landscape-resting CTAs. */
  .stay-back-home {
    position: relative;
    z-index: 1;
    margin: var(--space-7) auto 0;
    align-self: center;
  }
  .stay-back-home-icon {
    width: 13px;
    height: 13px;
    margin-right: 7px;
    flex-shrink: 0;
  }

  /* Quiet withdraw link — sits under the back-home pill. Subtle by
     design; this is a serious-but-rare action. */
  .stay-withdraw-link {
    position: relative;
    z-index: 1;
    display: block;
    margin: var(--space-4) auto var(--space-6);
    text-align: center;
    font-family: var(--sans);
    font-size: 13px;
    color: rgba(255, 255, 255, 0.80);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
  }
  .stay-withdraw-link:hover { color: #fff; }

  /* Clipboard tray — thin true-black band; the white paper sheet floats
     above it on a drop shadow. Applies to both the gathering folder (host)
     and a participant.s stay within a gathering — host and guest views of
     a gathering read the same. Solo stays (.solo-tray) skip the tray. */
  .stay-board-tray {
    position: relative;
    z-index: 2;
    width: 100%;
    max-width: 980px;
    padding: 14px 12px 12px;
    background: #000;
    border-radius: 0;
  }
  .stay-board-tray.solo-tray {
    padding: 0;
    background: transparent;
  }

  .stay-board {
    position: relative;
    /* z-index: 2 lifts the board (and everything inside it — modals,
       the host-picker dropdown, etc.) above .stay-back-home and
       .stay-withdraw-link below, both of which sit at z-index: 1.
       Without this, a dropdown that extends past the paper's bottom
       edge renders behind the glass back-home button. */
    z-index: 2;
    width: 100%;
    max-width: none;
    background: var(--paper);
    border-radius: 0;
    box-shadow:
      0 2px 10px rgba(0, 0, 0, 0.30),
      0 18px 50px rgba(0, 0, 0, 0.20);
    padding: 0 80px 72px;
    /* Establish a block formatting context so the clip's negative top
       margin pulls only the clip up — without flow-root, that margin
       would collapse through and drag the paper out of the tray. */
    display: flow-root;
  }
  .stay-board-content {
    position: relative;
    z-index: 0;
    /* Was 100px to clear the clip; with the clip gone this is just the
       sheet's top breathing room. */
    padding-top: 52px;
    transition: opacity 320ms ease;
  }

  /* When a card is layered on top AND not in pending state, dim the
     prep CONTENT to ~22% opacity. Pending == card is animating in or
     out: in those phases prep returns to full opacity, fading back as
     the card slides away. */
  .stay-shell--modal-open:not([data-stay-modal-pending]) .stay-board-content {
    opacity: 0.22;
    /* Disable clicks on the dimmed content while a modal is open. The
       click event still bubbles to .stay-shell (where the dismiss
       action lives), but nothing inside the dimmed area can be
       activated. */
    pointer-events: none;
  }
  .stay-board-content { transition: opacity 320ms ease; }

  /* ── Anchored clip ──
     Sticky inside the board's flow. As the page scrolls, the clip
     scrolls with content until its top edge would pass viewport
     top - 28; from there it sticks (top portion cut off, bottom half
     remains visible). */
  /* Sticky clip — top cut off but stops short of the engraved label
     (which sits at y=18 inside the clip), so "Corkins Exchange 2026"
     stays fully readable when pinned. The clip is part of the board's
     identity and stays visible through every state — including modal
     entrance and close — so we don't gate it on the pending flag. */
  .stay-board-clip {
    /* polish/ui-simplification: clip removed. The modal no longer tucks
       under it (it's a plain fade-in modal now), and the board's top
       breathing room comes from .stay-board-content. Reverse by restoring
       display:block. */
    display: none;
    position: sticky;
    /* Sticky anchor: when pinned, the lever curve and the very top of
       the body are clipped above the fold, but rivets + body + bar all
       still read. */
    top: -44px;
    width: 370px;
    height: 79px;
    /* Default position — clip sits with its lever cresting well above
       the tray top; bar overlaps the paper below. */
    margin: -52px auto -50px;
    z-index: 60;
    cursor: pointer;
  }
  .stay-board-clip:focus { outline: none; }
  .stay-board-clip:focus-visible {
    outline: 2px solid var(--ink);
    outline-offset: 2px;
    border-radius: 6px;
  }

  /* ── Summoned card ──
     Absolute on the board, centered. Scrolls with the page. Slides up
     from below on entry. Each card variant is its own designed thing —
     distinct paper, decorations, padding, etc. */
  /* Card sits at the top of the board, aligned with the clip's flow
     position. The card's internal padding-top makes room for the clip
     overlap so the heading and form fields never collide with the clip
     visually — even as the user scrolls and the clip's bottom half stays
     pinned at the top of the viewport. */
  .stay-modal-card {
    position: absolute;
    top: 0;
    left: 50%;
    width: 760px;
    max-width: calc(100% - 48px);
    z-index: 2;
    background: var(--paper);
    /* Square corners — modal cards read as printed sheets, not pill chrome. */
    border-radius: 0;
    box-shadow:
      0 1px 0 rgba(0,0,0,0.04),
      0 4px 10px rgba(0, 0, 0, 0.09);
    padding: 64px 60px 64px;
    transform: translate(-50%, 0);
    opacity: 1;
    /* Regular modal: a quiet fade-and-settle in place — no slide-from-bottom. */
    transition: opacity 240ms ease, transform 240ms ease;
  }
  .stay-shell[data-stay-modal-pending] .stay-modal-card {
    opacity: 0;
    transform: translate(-50%, 10px);
  }

  /* Close affordance — small ring with an X glyph, sits at the card's
     top-right corner. Click-outside also dismisses (handled by the
     stay-modal Stimulus controller). */
  .stay-modal-close {
    position: absolute;
    top: 18px;
    right: 22px;
    width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: none;
    color: var(--ink-faint);
    font-size: 16px;
    line-height: 1;
    text-decoration: none;
    z-index: 3;
    transition: color 0.15s ease;
  }
  .stay-modal-close:hover {
    color: var(--ink);
    text-decoration: none;
  }

  /* ── Profile card variant ──
     Warm short-form paper, narrower, soft top gradient. */
  .stay-modal-card--short-form {
    width: 620px;
    background: linear-gradient(180deg, var(--paper-warm) 0%, var(--paper-warm-2) 100%);
    box-shadow:
      0 1px 0 rgba(0,0,0,0.04),
      0 4px 10px rgba(0, 0, 0, 0.09);
  }

  /* ── Logistics / todo card variant ──
     Index-card aesthetic: rounded by default, faint inner shading,
     ruled hairline near the top, slightly cooler paper. Square edges
     are opt-in per modal (tone-lined for the stay todo; the host ask
     gets squared via the .ask-modal-paper selector below). */
  .stay-modal-card--index-card {
    width: 760px;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.018) 0%, transparent 8%, transparent 92%, rgba(0,0,0,0.025) 100%),
      var(--paper);
  }
  /* Host-side ask edit modal wraps its content in .ask-modal-paper
     (ruled paper with negative margins to fill the card). Square the
     outer card so the lined inner doesn't sit inside a rounded shell. */
  .stay-modal-card:has(.ask-modal-paper) {
    border-radius: 0;
  }
  /* The task editor is clean & solid — drop the index-card hairline rule. */
  .stay-modal-card:has(.ask-modal-paper)::after {
    display: none;
  }
  .stay-modal-card--index-card::after {
    content: '';
    position: absolute;
    left: 32px; right: 32px;
    top: 44px;
    height: 1px;
    background: var(--arrive-ring);
    pointer-events: none;
  }
  /* When the index-card carries a to-do header (logistics modal restyled to
     match the task cards), drop the hairline so it doesn't cut the badge. */
  .stay-modal-card--index-card:has(.todo-head)::after { display: none; }

  /* ── Letter card variant ──
     Welcome-letter modal — warm paper with the same texture as the
     stationery preview, square edges so it reads as a sheet of paper
     pulled out of a folder rather than a rounded UI panel. */
  .stay-modal-card--letter {
    width: 760px;
    border-radius: 0;
    background-color: var(--paper-warm);
    background-image: var(--paper-texture);
    background-repeat: repeat;
    background-size: 480px auto;
  }

  /* ── Tone variants — paint the whole modal card. ── */
  .stay-modal-card--tone-arrive,
  .stay-modal-card--tone-depart {
    width: 560px;
    padding: 48px 44px 40px;
  }
  .stay-modal-card--tone-arrive {
    background: var(--arrive-paper);
  }
  .stay-modal-card--tone-arrive.stay-modal-card--index-card {
    width: 560px;
    padding: 48px 44px 40px;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.02) 0%, transparent 8%, transparent 92%, rgba(0,0,0,0.03) 100%),
      var(--arrive-paper);
  }
  .stay-modal-card--tone-arrive.stay-modal-card--index-card::after {
    display: none;
  }

  .stay-modal-card--tone-depart {
    background: var(--depart-paper);
  }
  .stay-modal-card--tone-depart.stay-modal-card--index-card {
    width: 560px;
    padding: 48px 44px 40px;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.02) 0%, transparent 8%, transparent 92%, rgba(0,0,0,0.03) 100%),
      var(--depart-paper);
  }
  .stay-modal-card--tone-depart.stay-modal-card--index-card::after {
    display: none;
  }

  /* Neutral tone — same card treatment, paper-warm ground. */
  .stay-modal-card--tone-neutral {
    width: 560px;
    padding: 48px 44px 40px;
    background: var(--paper-warm);
  }
  .stay-modal-card--tone-neutral.stay-modal-card--index-card {
    width: 560px;
    padding: 48px 44px 40px;
    background:
      linear-gradient(180deg, rgba(0,0,0,0.02) 0%, transparent 8%, transparent 92%, rgba(0,0,0,0.03) 100%),
      var(--paper-warm);
  }
  .stay-modal-card--tone-neutral.stay-modal-card--index-card::after {
    display: none;
  }

  /* Lined-paper tone — for todo modals. Square corners, no inner
     frame; the lined paper carries the texture instead. */
  .stay-modal-card--tone-lined,
  .stay-modal-card--tone-lined.stay-modal-card--index-card {
    width: 560px;
    padding: 48px 44px 40px;
    border-radius: 0;
    background-color: #fff;
    background-image:
      linear-gradient(to right,
        transparent 32px,
        rgba(0, 0, 0, 0.12) 32px,
        rgba(0, 0, 0, 0.12) 34px,
        transparent 34px),
      repeating-linear-gradient(
        to bottom,
        transparent 0,
        transparent 31px,
        rgba(0, 0, 0, 0.05) 31px,
        rgba(0, 0, 0, 0.05) 32px
      );
  }
  .stay-modal-card--tone-lined.stay-modal-card--index-card::after {
    display: none;
  }

  /* ── Task card variant ──
     Clean, solid sheet for the to-do experience. No lined paper, no
     printed-frame, no rotated stamps — just a white card with quiet
     shadow so structured content (checkout, uploads) reads as robust
     and trustworthy. Narrower than the default sheet to stay focused. */
  .stay-modal-card--task {
    width: 600px;
    padding: 40px 44px 36px;
    background: #fff;
    box-shadow:
      0 1px 0 rgba(0,0,0,0.04),
      0 8px 24px rgba(0,0,0,0.10),
      0 2px 6px rgba(0,0,0,0.06);
  }
  @media (max-width: 768px) {
    .stay-modal-card--task { padding: 32px 22px 28px; }
  }

  /* Inner printed-paper frame — a thin hairline drawn just inside the
     edges of any tone-treated modal card. The lined-paper tone opts
     out (its rule rhythm is the texture). */
  .stay-modal-card--tone-arrive::before,
  .stay-modal-card--tone-depart::before,
  .stay-modal-card--tone-neutral::before {
    content: '';
    position: absolute;
    top: 14px; right: 14px; bottom: 14px; left: 14px;
    border: 1px solid currentColor;
    pointer-events: none;
    border-radius: 4px;
  }
  .stay-modal-card--tone-arrive::before  { color: var(--arrive-line); }
  .stay-modal-card--tone-depart::before  { color: var(--depart-line); }
  .stay-modal-card--tone-neutral::before { color: rgba(0,0,0,0.14); }

  /* ── Mobile (≤ 768px) ── must come AFTER all base rules to override. */
  @media (max-width: 768px) {
    .stay-shell { padding: 84px 4px 32px; }
    .stay-nav { padding: 0 70px 0 16px; height: 64px; gap: 14px; }
    .stay-nav-brand {
      font-size: 17px;
      /* Allow the wordmark to wrap so the "+ New" CTA keeps its label. */
      white-space: normal;
      line-height: 1.05;
      min-width: 0;
      flex: 0 1 auto;
    }
    .stay-nav-link { font-size: 14px; }
    .stay-nav-avatar { width: 40px; height: 40px; font-size: 12px; }
    .stay-nav-avatar-wrap { top: 12px; right: 16px; }
    .stay-board-tray { padding: 16px 10px 10px; }
    .stay-board { padding: 0 14px 48px; }
    .stay-board-clip {
      width: 292px;
      max-width: calc(100% - 24px);
      height: 62px;
      top: -34px;
      margin: -40px auto -40px;
    }

    .stay-modal-card,
    .stay-modal-card--short-form,
    .stay-modal-card--index-card,
    .stay-modal-card--tone-arrive,
    .stay-modal-card--tone-arrive.stay-modal-card--index-card,
    .stay-modal-card--tone-depart,
    .stay-modal-card--tone-depart.stay-modal-card--index-card,
    .stay-modal-card--tone-neutral,
    .stay-modal-card--tone-neutral.stay-modal-card--index-card,
    .stay-modal-card--tone-lined,
    .stay-modal-card--tone-lined.stay-modal-card--index-card {
      width: calc(100% - 16px);
      max-width: calc(100% - 16px);
      /* Top padding is bigger so the sticky clip doesn't overlap the
         direction title or date stamp at the top of the card. */
      padding: 64px 22px 28px;
    }
    /* Lined-paper modal — keep the pink Cornell rule hugging the left
       edge on phones so it no longer crosses the checkbox or title. */
    .stay-modal-card--tone-lined,
    .stay-modal-card--tone-lined.stay-modal-card--index-card {
      background-image:
        linear-gradient(to right,
          transparent 10px,
          rgba(0, 0, 0, 0.12) 10px,
          rgba(0, 0, 0, 0.12) 12px,
          transparent 12px),
        repeating-linear-gradient(
          to bottom,
          transparent 0,
          transparent 31px,
          rgba(0, 0, 0, 0.05) 31px,
          rgba(0, 0, 0, 0.05) 32px
        );
    }
    .stay-modal-card--tone-arrive::before,
    .stay-modal-card--tone-depart::before,
    .stay-modal-card--tone-neutral::before {
      top: 8px; right: 8px; bottom: 8px; left: 8px;
    }
    .stay-modal-close { top: 12px; right: 14px; }
  }
}
