/* The Island home: mobile first, on Atoll's brand (brand.css: the palette, the faces, actions,
   focus and the logo). This file lays out the shell's pages with those tokens. Readability
   rules from the guide: body 16px, nothing under 14px, controls at least 44px tall, reflow
   rather than shrink, no horizontal scroll on a phone. Since task 36b (item 15) every paragraph,
   note, hint and list line is 16px too; only labels, badges and a record's field names are
   smaller, never under 14px. */

:root {
  --gutter: 16px;
  --line: var(--atoll-line);
  --radius: var(--atoll-radius);
}

*, *::before, *::after { box-sizing: border-box; }

body {
  min-height: 100vh;
  min-height: 100dvh;
}

h1 { font-size: 2rem; line-height: 1.12; margin: .25rem 0 .75rem; overflow-wrap: anywhere; }
h2 { font-size: 1.375rem; line-height: 1.25; margin: 2rem 0 .5rem; }
h3 { font-size: 1.0625rem; line-height: 1.35; margin: 1.5rem 0 .25rem; }
p { margin: 0 0 .75rem; }
/* A long unbroken word (an Island's name, a person's) wraps anywhere rather than push a page
   sideways at 390px (task 34). A flex child also needs `min-width: 0` to shrink below that word,
   as the text beside a checkbox in a `.check` row does. */
h2, h3, p, legend, .hint, .check > span, .event-meta { overflow-wrap: anywhere; }
.check > span { min-width: 0; }

.note { color: var(--atoll-forest-soft); }
.lede { font-size: 1.125rem; line-height: 1.6; color: var(--atoll-forest-soft); max-width: 36rem; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip { position: absolute; left: -9999px; top: 0; }
.skip:focus {
  left: var(--gutter); top: 8px; z-index: 10;
  display: inline-flex; align-items: center; min-height: 44px; padding: .5rem 1.125rem;
  border-radius: var(--atoll-pill); background: var(--atoll-forest); color: var(--atoll-paper);
  font-weight: 600; text-decoration: none;
}

input, select { width: 100%; }
label { font-weight: 600; }

.stack { display: flex; flex-direction: column; gap: .5rem; margin: 1rem 0; }
.stack button { align-self: flex-start; margin-top: .5rem; }

/* The bar along the top of every signed-in page: on a phone the Atoll symbol with the Island's
   name and Sign out, who is signed in on a line of its own, and the page links below, wrapping
   onto a second row rather than scrolling out of sight; wider, all on one row. The symbol keeps
   half its width clear on every side (the padding and gaps below). */
.bar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "brand account" "nav nav";
  align-items: center;
  gap: .375rem 1rem;
  padding: .75rem var(--gutter) .5rem;
  padding-top: max(.75rem, env(safe-area-inset-top));
  border-bottom: 1px solid var(--line);
  background: var(--atoll-paper);
}
.brand {
  grid-area: brand;
  display: inline-flex;
  align-items: center;
  gap: 14px;
  min-height: 44px;
  font-weight: 600;
  font-size: 1.125rem;
  letter-spacing: -.01em;
  color: var(--atoll-forest);
  text-decoration: none;
  overflow-wrap: break-word;
  min-width: 0;
}
.brand span { min-width: 0; }
.brand:hover span { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .2em; }
.brand [data-atoll-logo] { width: 28px; height: 28px; }
/* The account button (task 17e): the member's initial in a Forest circle, and their name beside it
   once there is room (on a phone the circle alone; the name stays for screen readers). A Clay dot
   on the circle while the member has no passkey. Its menu drops below it, Paper with a Forest edge
   like the cards, never covering the page as a dialog would. */
.account { grid-area: account; position: relative; justify-self: end; }
/* Until the member is known on a cold start with nothing kept (task 55). */
.account[hidden] { display: none; }
.account-button {
  min-height: 44px;
  min-width: 44px;
  padding: 0 .25rem;
  gap: .625rem;
  border-color: transparent;
  background: transparent;
  box-shadow: none;
  font-weight: 500;
  font-size: .9375rem;
}
.account-button:hover, .account-button[aria-expanded="true"] { background: var(--atoll-new-leaf-tint); border-color: var(--atoll-forest); box-shadow: none; }
.avatar {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--atoll-forest);
  color: var(--atoll-paper);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
}
.passkey-dot {
  position: absolute;
  top: -2px;
  right: -3px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--atoll-clay);
  border: 2px solid var(--atoll-paper);
}
.who {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.account-popover {
  position: absolute;
  top: calc(100% + .5rem);
  right: 0;
  z-index: 20;
  width: min(20rem, calc(100vw - 2 * var(--gutter)));
  padding: .5rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: 18px;
  background: var(--atoll-paper);
  box-shadow: 0 4px 0 var(--atoll-forest);
}
.account-popover[hidden] { display: none; }
.account-head { padding: .5rem .75rem .75rem; margin-bottom: .25rem; border-bottom: 1px solid var(--line); }
.account-head p { margin: 0; overflow-wrap: anywhere; }
.account-name { font-weight: 600; }
.account-email { color: var(--atoll-forest-soft); font-size: 1rem; }
.account-email:empty { display: none; }
.account-item, button.account-item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 44px;
  padding: .5rem .75rem;
  border: 0;
  border-radius: 12px;
  background: transparent;
  box-shadow: none;
  color: var(--atoll-forest);
  font: inherit;
  font-weight: 500;
  text-align: left;
  text-decoration: none;
  justify-content: flex-start;
  overflow-wrap: anywhere; /* "You on <Island>" with a long name wraps (task 46). */
}
.account-item:hover, .account-item:focus-visible, button.account-item:hover { background: var(--atoll-new-leaf-tint); box-shadow: none; color: var(--atoll-forest); }
.account-item:focus-visible { outline: 3px solid var(--atoll-forest); outline-offset: -3px; }
/* The passkey item: a Clay-tinted block at the top of the menu while there is no passkey. */
.account-nudge { margin: .25rem 0 .375rem; }
/* The account-wide items (my.<domain>, signing out) apart from this Island's. */
.account-popover .account-link { margin-top: .375rem; position: relative; }
.account-popover .account-link::before { content: ""; position: absolute; left: .75rem; right: .75rem; top: -.25rem; border-top: 1px solid var(--line); }
button.nudge-item { flex-direction: column; align-items: flex-start; gap: .125rem; background: var(--atoll-clay-tint); }
button.nudge-item:hover { background: #FFC4AF; }
.nudge-title { font-weight: 600; }
.nudge-sub { font-size: 1rem; font-weight: 400; }
.nudge-problem { margin: .25rem .75rem 0; font-size: 1rem; color: var(--atoll-alert); font-weight: 600; }
.nudge-problem:empty { display: none; }

.site-nav {
  grid-area: nav;
  display: flex;
  /* One row, never an orphan (task 55): the links fit at 390px; a row that still cannot fit (a
     narrower screen, a larger text size) scrolls sideways inside the bar, with no scrollbar shown.
     The padding keeps the focus ring clear of the scroll box's edge. */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  gap: .25rem;
  padding: 4px;
  margin: 0 -4px;
}
.site-nav::-webkit-scrollbar { display: none; }
.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 .75rem;
  border-radius: var(--atoll-pill);
  color: var(--atoll-forest);
  text-decoration: none;
  white-space: nowrap;
}
.site-nav a:hover { background: var(--atoll-new-leaf-tint); }
.site-nav a[aria-current="page"] { background: var(--atoll-new-leaf); font-weight: 600; box-shadow: inset 0 0 0 1.5px var(--atoll-forest); }
@media (max-width: 29.99rem) {
  .site-nav { gap: 0; justify-content: space-between; }
  .site-nav a { padding: 0 .5rem; font-size: .9375rem; }
}
/* Narrower than 390px (a 320px phone): 14px, the guide's floor, and the least padding. */
@media (max-width: 24.3rem) {
  .site-nav a { padding: 0 .1875rem; font-size: .875rem; }
}

/* An app in its frame on a phone: the symbol alone, the page links and Sign out flow together
   in one wrapping run (two rows on a phone), leaving most of the screen to the app. The nav keeps
   its landmark; only its box gives way so its links can share rows with Sign out. The Island's
   name stays the home link's name for screen readers; "Signed in as" is on every other page. */
@media (max-width: 59.99rem) {
  body.framed .bar { display: flex; flex-wrap: wrap; align-items: center; gap: .375rem .25rem; padding-bottom: .5rem; }
  body.framed .brand { margin-right: .625rem; }
  body.framed .brand #island-name {
    position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
  }
  body.framed .site-nav { display: contents; }
  body.framed .site-nav a { padding: 0 .625rem; }
  body.framed .account { margin-left: auto; }
}
/* The "Menu" button (task 36b): only on an app's page at 600px or less, where the page links fold
   behind it so the app starts higher. Closed, the links are gone (not focusable); open, they take
   a row of their own under the bar's first row. The app bar and any band are untouched. */
.nav-toggle { display: none; }
@media (max-width: 37.5rem) {
  body.framed .nav-toggle {
    display: inline-flex;
    order: 1;
    min-height: 44px;
    padding: 0 1rem 0 .75rem;
    gap: .5rem;
    background: var(--atoll-paper);
    box-shadow: none;
    font-weight: 500;
  }
  body.framed .nav-toggle:hover { background: var(--atoll-new-leaf-tint); color: var(--atoll-forest); }
  body.framed .nav-toggle[aria-expanded="true"] { background: var(--atoll-new-leaf-tint); }
  body.framed .account { order: 2; }
  body.framed .nav-toggle[aria-expanded="false"] ~ .site-nav { display: none; }
  body.framed .nav-toggle[aria-expanded="true"] ~ .site-nav { display: flex; order: 3; flex-basis: 100%; flex-wrap: wrap; gap: .375rem .25rem; margin: .125rem 0 0; }
}

@media (min-width: 48rem) {
  :root { --gutter: 32px; }
}
/* Wide enough for one row: the Island, the page links, who is signed in, Sign out. */
@media (min-width: 60rem) {
  .bar {
    grid-template-columns: auto auto minmax(0, 1fr) auto;
    grid-template-areas: "brand nav . account";
    gap: 0 1.5rem;
    padding-top: max(1rem, env(safe-area-inset-top));
    padding-bottom: 1rem;
  }
  .brand { font-size: 1.25rem; max-width: 18rem; }
  .brand [data-atoll-logo] { width: 32px; height: 32px; }
  .brand { gap: 16px; }
  .site-nav { margin: 0; flex-wrap: nowrap; }
  /* Room for the name beside the circle. */
  .account-button { padding: 0 1rem 0 .3125rem; }
  .who { position: static; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: nowrap; max-width: 14rem; text-overflow: ellipsis; overflow: hidden; color: var(--atoll-forest); }
}

/* Atoll has paused this Island's apps (task 29): one calm band under the bar on every page, on
   Daydream's tint like the framed app's offline line; not an alert, nothing to dismiss. */
.island-paused {
  padding: .75rem var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--atoll-daydream-tint);
  color: var(--atoll-forest);
}
.island-paused p { margin: 0; max-width: 44rem; font-size: 1rem; line-height: 1.45; }
.island-paused strong { font-weight: 600; }

main {
  display: block;
  max-width: 44rem;
  margin: 0 auto;
  padding: 1.75rem var(--gutter) 3.5rem;
}
main:focus { outline: none; }

.card {
  margin-top: 2rem;
  padding: .5rem 1.25rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--atoll-surface);
}
.card > h2:first-child { margin-top: 1rem; }
.card > p:last-child { margin-bottom: 0; }
.card + section:not(.card) { margin-top: 2rem; }

/* The home page: the Island's name, then its apps as tiles on Paper, each led by its icon. */
.home-head { margin-bottom: 1.5rem; }
.home-head h1 { font-size: 2.5rem; line-height: 1.05; margin-bottom: .5rem; }
.home-head .lede { max-width: 40rem; }
.apps { list-style: none; margin: 0 0 1rem; padding: 0; display: grid; gap: .75rem; }
.app {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .5rem .75rem;
  min-height: 5.5rem;
  padding: 1rem 1.25rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: var(--radius);
  /* One surface for every tile (task 55): Paper with the Forest edge; the icon carries the app's colour. */
  background: var(--atoll-paper);
}
.app a {
  flex: 1 1 12rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-width: 0;
  min-height: 44px;
  font-weight: 600;
  font-size: 1.1875rem;
  letter-spacing: -.01em;
  color: var(--atoll-forest);
  text-decoration: none;
  overflow-wrap: break-word;
}
/* The whole tile opens the app. */
.app a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; }
/* Focus: the link's own ring everywhere; where :has() is known, the ring goes round the whole tile. */
.app a:focus-visible { outline-offset: 6px; }
@supports selector(:has(*)) {
  .app a:focus-visible { outline: none; }
  .app:has(a:focus-visible) { outline: 3px solid var(--atoll-forest); outline-offset: 3px; }
}
.app a:hover .app-name { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .2em; }
.app .go { font-size: 1.375rem; line-height: 1; font-weight: 400; }
.app.paused { background: var(--atoll-paper); border-style: dashed; border-color: var(--atoll-edge); }
.app.paused a { color: var(--atoll-forest-soft); }
.app .badge { position: relative; }

.badge {
  display: inline-block;
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.4;
  padding: .125rem .625rem;
  border-radius: var(--atoll-pill);
  background: var(--atoll-clay-tint);
  color: var(--atoll-forest);
}

/* The home page with no app yet (task 17e): the brand's own workflow, three large steps on the
   accent surfaces (New leaf, Daydream, Clay) with forest text, as the page's main content. Wider,
   the page gives them room for three columns. */
main:has(.loop) { max-width: 74rem; }
.loop { margin-top: 2.25rem; }
.loop > h2 { margin: 0 0 1.25rem; }
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1rem; }
.step {
  display: flex;
  flex-direction: column;
  min-width: 0;
  padding: 1.25rem 1.25rem 1.5rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: 22px;
  color: var(--atoll-forest);
}
.step-ask { background: var(--atoll-new-leaf); }
.step-publish { background: var(--atoll-daydream); }
.step-use { background: var(--atoll-clay); }
.step-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.step-icon { width: 52px; height: 52px; flex: none; margin-top: .25rem; }
.step-num {
  font-family: var(--atoll-serif);
  font-style: italic;
  font-size: 3.5rem;
  line-height: 1;
  letter-spacing: -.03em;
}
.step h3 { font-size: 1.5rem; font-weight: 500; letter-spacing: -.025em; line-height: 1.2; margin: .5rem 0 .625rem; overflow-wrap: anywhere; }
.step p { margin: 0 0 .75rem; }
.step p:last-child { margin-bottom: 0; }
.step a { color: var(--atoll-forest); font-weight: 600; }
.connector { display: flex; flex-wrap: wrap; align-items: stretch; gap: .5rem; margin: 0 0 .75rem; }
.connector-url {
  /* Its own width first, so the button moves to the next row before the address breaks. */
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  min-height: 48px;
  padding: .5rem .875rem;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 1rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
  border: 1.5px solid var(--atoll-forest);
  border-radius: 12px;
  background: var(--atoll-paper);
  -webkit-user-select: all;
  user-select: all;
}
/* The action on an accent surface: forest, so it stands off New leaf. */
button.on-accent { background: var(--atoll-forest); color: var(--atoll-paper); box-shadow: none; min-width: 6.5rem; }
button.on-accent:hover { background: #24483A; box-shadow: none; }
.step .where { font-size: 1rem; }
.step .where .path { font-weight: 600; }
.example {
  font-family: var(--atoll-serif);
  font-style: italic;
  font-size: 1.75rem;
  line-height: 1.15;
  letter-spacing: -.015em;
}
.copy-status { display: block; margin: -.25rem 0 .75rem; font-size: 1rem; font-weight: 500; }
.copy-status:empty { display: none; }

/* With apps: the same steps behind a quiet link below the list. */
.make-app { margin-top: 1.25rem; }
.make-app > summary {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  min-height: 44px;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
}
.make-app > summary::-webkit-details-marker { display: none; }
.make-app > summary::before { content: "+"; display: inline-block; width: 1em; text-align: center; font-weight: 500; font-size: 1.25rem; line-height: 1; }
.make-app[open] > summary::before { content: "\2212"; }
.make-app > summary span { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: .2em; }
.make-app > summary:hover span { text-decoration-thickness: 2px; }
.make-app .steps { margin-top: .75rem; gap: .75rem; }
.make-app .step-num { font-size: 2.75rem; }
.make-app .step-icon { width: 40px; height: 40px; }
.make-app .step h3 { font-size: 1.3125rem; }

/* Pages with a heading and a lede (/you, /settings). */
.page-head { margin-bottom: .5rem; }
.page-head .lede { max-width: 40rem; }

/* /you: your name on this Island, your daily email from it, and Claude on it (task 46). */
#my-name { margin-bottom: 0; }
#my-name .hint-line { font-size: 1rem; margin: -.25rem 0 .25rem; }
#my-name-input { max-width: 26rem; }
#my-name-input[aria-invalid="true"] { border-color: var(--atoll-alert); border-width: 2px; }
.field-problem { margin: 0; color: var(--atoll-alert); font-weight: 600; }
.field-problem:empty { display: none; }
#you .connections > li:last-child { border-bottom: 0; padding-bottom: 0; }

/* /settings: the administrators. */
.admins { list-style: none; margin: .25rem 0 .75rem; padding: 0; }
.admins > li { padding: .625rem 0; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
.approval-state { font-weight: 600; }

/* An action that removes something (a person, a passkey, an invite link, a connection): quiet,
   with forest text, but on a Clay edge so it does not read like a harmless one. */
button.danger { border-color: var(--atoll-clay-deep); border-width: 2px; }
button.danger:hover { background: var(--atoll-clay-tint); color: var(--atoll-forest); border-color: var(--atoll-clay-deep); }
button.danger:disabled { border-color: var(--atoll-edge); }

/* A refusal from the API, in the page's one role="alert" element; empty takes no room. */
.alert {
  color: var(--atoll-alert);
  font-weight: 600;
  padding: .75rem 1rem;
  border-left: 4px solid var(--atoll-clay);
  background: var(--atoll-surface);
  border-radius: 0 10px 10px 0;
}
.alert:empty, .note[role="status"]:empty, #people-status:empty, #settings-status:empty { display: none; }
.note[role="status"] { font-weight: 500; }

select {
  width: auto;
  padding-right: 2.25rem;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--atoll-forest) 50%), linear-gradient(135deg, var(--atoll-forest) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 12px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* People, invite links, connections: one row per item, the controls at the end. */
.people, .invites, .connections { list-style: none; margin: 0 0 .5rem; padding: 0; }
.people > li, .invites > li, .connections > li {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: .125rem .75rem;
  align-items: center;
  padding: .875rem 0;
  border-bottom: 1px solid var(--line);
}
.people > li > :not(.person-controls), .invites > li > :not(button), .connections > li > :not(button) { grid-column: 1; }
.people > li .note, .invites > li .note, .connections > li .note { font-size: 1rem; margin: 0; }
.person-name, .connection-name { font-weight: 600; overflow-wrap: break-word; min-width: 0; }
.you { font-weight: 400; color: var(--atoll-forest-soft); }
.person-controls { grid-column: 2; grid-row: 1 / span 2; display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .5rem; }
.invites > li > button, .connections > li > button { grid-column: 2; grid-row: 1 / span 3; }
@media (max-width: 29.99rem) {
  .person-controls { grid-column: 1 / -1; grid-row: auto; justify-content: flex-start; margin-top: .5rem; }
}

.invite-made:not(:empty), .keep:not(:empty) {
  margin: 1rem 0;
  padding: 1rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: var(--radius);
  background: var(--atoll-new-leaf-tint);
}
.invite-made .note, .keep .note { font-size: 1rem; margin: .25rem 0 .75rem; }
.copy-row { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }
.copy-row input { flex: 1 1 14rem; font-size: 1rem; }
.copy-actions { display: flex; flex-wrap: wrap; gap: .75rem; }

/* Task 36c, the sender: "Invite someone" first, its short form, the note on a live link, the
   role picker after "Change", whom a member asks, and the in-page confirmation of a removal. */
.invites-section .invite-start { margin: 1rem 0 .5rem; }
.invite-form { display: flex; flex-direction: column; gap: .5rem; margin: 1rem 0; max-width: 30rem; }
.invite-form[hidden] { display: none; }
.invite-form .note { font-size: 1rem; margin: 0; }
.form-actions { display: flex; flex-wrap: wrap; gap: .75rem; margin-top: .5rem; }
.invite-for { font-weight: 600; overflow-wrap: anywhere; min-width: 0; }
.role-picker select { min-width: 10rem; }
.ask-admin:empty { display: none; }
dialog.confirm {
  max-width: min(28rem, calc(100vw - 2rem));
  padding: 1.25rem 1.25rem 1.5rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: 18px;
  background: var(--atoll-paper);
  color: var(--atoll-forest);
  box-shadow: 0 5px 0 var(--atoll-forest);
}
dialog.confirm::backdrop { background: rgba(16, 44, 32, .45); }
dialog.confirm p { margin: 0 0 1.25rem; font-size: 1rem; }
.confirm-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: .75rem; }
/* At phone width the two answers stack, full width, rather than wrap unevenly (task 55). */
@media (max-width: 29.99rem) {
  .confirm-actions { flex-direction: column-reverse; align-items: stretch; }
  .confirm-actions button { width: 100%; }
}

/* Daily email: one checkbox per collection. */
fieldset.digest { border: 0; margin: 0; padding: 0; }
fieldset.digest legend { font-weight: 600; padding: 0; margin-bottom: .25rem; }
fieldset.digest ul { list-style: none; margin: 0; padding: 0; }
fieldset.digest li { padding: .125rem 0; }
.check { display: flex; align-items: center; gap: .75rem; min-height: 44px; font-weight: 500; cursor: pointer; }
.check input { width: 1.375rem; height: 1.375rem; min-height: 0; margin: 0; flex: none; accent-color: var(--atoll-forest); }
.hint { display: block; font-size: 1rem; margin: -.25rem 0 .375rem 2.125rem; }

.message { padding-top: 1.5rem; }

/* An app in its frame: the bar, a slim app bar, and the frame filling the rest. */
body.framed { display: flex; flex-direction: column; height: 100vh; height: 100dvh; overflow: hidden; }
body.framed main { flex: 1; display: flex; flex-direction: column; max-width: none; width: 100%; padding: 0; min-height: 0; }
.app-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem .75rem;
  padding: .375rem var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--atoll-new-leaf-tint);
}
.app-bar a { color: var(--atoll-forest); font-weight: 500; }
.app-bar .back {
  display: inline-flex; align-items: center; gap: .25rem;
  min-height: 44px; padding: 0 .875rem 0 .625rem;
  border: 1.5px solid var(--atoll-forest); border-radius: var(--atoll-pill);
  background: var(--atoll-paper);
  text-decoration: none; white-space: nowrap;
}
.app-bar .back:hover { background: var(--atoll-forest); color: var(--atoll-paper); }
.app-title { flex: 1 1 8rem; font-size: 1.0625rem; font-weight: 600; letter-spacing: -.01em; line-height: 1.3; margin: 0; min-width: 0; overflow-wrap: break-word; }
.app-bar .about { margin-left: auto; min-height: 44px; display: inline-flex; align-items: center; white-space: nowrap; }
#app-frame { flex: 1; width: 100%; min-height: 0; border: 0; background: #fff; }
/* The framed app reports it is offline (task 20): one quiet line above the frame. */
.app-offline {
  margin: 0;
  padding: .375rem var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--atoll-daydream-tint);
  color: var(--atoll-forest);
  font-size: 1rem;
  font-weight: 500;
}
.app-offline[hidden] { display: none; }
/* The framed app never reported it started (task 27a1): a calm band above the frame, like the
   paused notice; its live region (#app-start) sits empty until then. */
.app-not-started {
  padding: .75rem var(--gutter);
  border-bottom: 1px solid var(--line);
  background: var(--atoll-daydream-tint);
  color: var(--atoll-forest);
}
.app-not-started p { margin: 0; max-width: 44rem; font-size: 1rem; line-height: 1.45; }
.app-not-started strong { font-weight: 600; }
.app-not-started .actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem 1.25rem; margin-top: .625rem; }
.app-not-started .actions a { min-height: 44px; display: inline-flex; align-items: center; color: var(--atoll-forest); font-weight: 500; }

/* A standalone text link (task 55: "All collections", "Back to your apps", "About this app"): 44px
   tall to touch, like every other control. */
a.way { display: inline-flex; align-items: center; min-height: 44px; }

/* The approval setting's "How it works" (task 55). */
.how-it-works { margin: 0 0 .75rem; }
.how-it-works > summary { display: flex; align-items: center; min-height: 44px; font-weight: 600; cursor: pointer; }
.how-it-works > p { margin-top: .25rem; }

/* A link that looks like a button (the export download): brand.css draws it. */
a.button:hover { text-decoration: none; }

/* The app page. */
.crumbs { display: flex; flex-wrap: wrap; gap: .25rem 1.25rem; }
.crumbs a { display: inline-flex; align-items: center; min-height: 44px; }
.controls { margin: 1rem 0; }
.controls .note { margin-top: .75rem; font-size: 1rem; }
.summary-text { white-space: pre-line; overflow-wrap: anywhere; }
.versions { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }
.version { padding: 1rem 1.25rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--atoll-surface); }
.version.current { border: 1.5px solid var(--atoll-forest); box-shadow: 0 3px 0 var(--atoll-forest); }
.version h3 { font-size: 1.0625rem; margin: 0 0 .25rem; display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; }
.version .badge { background: var(--atoll-new-leaf); }
.version .note { font-size: 1rem; margin-bottom: .5rem; }
.version .changelog { overflow-wrap: anywhere; white-space: pre-line; }
.version details { margin: 0 0 .5rem; }
.version summary { cursor: pointer; font-weight: 500; min-height: 44px; display: flex; align-items: center; text-decoration: underline; text-underline-offset: .2em; }
.version details .summary-text { font-size: 1rem; color: var(--atoll-forest-soft); }
/* An app's errors (task 27a2): each message as written, in the code face, wrapping anywhere at 390px. */
.error-list { list-style: none; margin: .75rem 0 1rem; padding: 0; }
.error-list li { padding: .625rem 0; border-bottom: 1px solid var(--line); min-width: 0; }
.error-list li:first-child { border-top: 1px solid var(--line); }
.error-message {
  margin: 0 0 .25rem;
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  font-size: 1rem;
  line-height: 1.4;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}
.error-list .note { margin: 0; font-size: 1rem; overflow-wrap: anywhere; }

/* The activity page. */
.events { list-style: none; margin: 1rem 0; padding: 0; }
.events li { display: flex; flex-direction: column; gap: .125rem; padding: .75rem 0; border-bottom: 1px solid var(--line); }
.events li:focus, .versions li:focus { outline: 3px solid var(--atoll-forest); outline-offset: 3px; }
.event-summary { overflow-wrap: anywhere; }
.event-meta { font-size: 1rem; }

/* The collection pages. */
.collections, .fields, .records, .can-see { list-style: none; margin: 0 0 .5rem; padding: 0; }
.collections { margin-top: 1.5rem; }
.collection {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0 .75rem;
  padding: .625rem 1.25rem .875rem; margin-bottom: .75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius); background: var(--atoll-surface);
}
.collection a { display: inline-flex; align-items: center; min-height: 44px; font-weight: 600; font-size: 1.125rem; text-decoration: none; overflow-wrap: break-word; min-width: 0; }
.collection a:hover .collection-name { text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: .2em; }
.collection > .note { flex-basis: 100%; font-size: 1rem; margin: 0; }
.collection .badge, h1 .badge { background: var(--atoll-daydream-tint); }
.fields > li, .can-see > li { padding: .5rem 0; border-bottom: 1px solid var(--line); overflow-wrap: anywhere; }
.field-name { font-weight: 600; }
.fields .note, .can-see .note { font-size: 1rem; }
.records > li { padding: .75rem 0; border-bottom: 1px solid var(--line); }
.records dl { display: grid; grid-template-columns: minmax(6rem, auto) minmax(0, 1fr); gap: .125rem .75rem; margin: 0; }
.records dt { color: var(--atoll-forest-soft); font-size: .875rem; padding-top: .125rem; }
.records dd { margin: 0; overflow-wrap: anywhere; white-space: pre-line; }
.records .note { font-size: 1rem; }
h1 .badge { vertical-align: middle; font-size: .875rem; letter-spacing: 0; font-weight: 500; }

/* The sign-in page: the Atoll lockup, the passkey first, the email link below; wider, a quiet
   contour drawing of an Island beside it (decorative, never behind text). */
.signin {
  max-width: 64rem;
  padding-top: 2rem;
}
.signin-lockup { height: 52px; width: auto; margin: 0 0 2rem; }
.signin-form { max-width: 28rem; }
.signin h1 { font-size: 2.5rem; line-height: 1.08; margin-bottom: 1rem; }
/* The Island's name (task 54) stays on one line when it fits and wraps anywhere when it is longer than the line. */
.signin h1 em { display: inline-block; max-width: 100%; }
.signin .passkey { margin: 1.5rem 0 2rem; }
.signin .or {
  display: flex; align-items: center; gap: 1rem;
  margin: 2rem 0 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
}
.signin .or h2 { margin: 0 0 .25rem; }
.signin-art { display: none; }

@media (min-width: 48rem) {
  main { padding-top: 2.5rem; }
  h1 { font-size: 2.75rem; }
  h2 { font-size: 1.5rem; }
  .home-head h1 { font-size: 3.25rem; }
  .apps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .step { padding: 1.5rem 1.75rem 1.75rem; }
  .step-num { font-size: 4rem; }
  .signin { padding-top: 3rem; }
  .signin h1 { font-size: 3.25rem; }
}

/* Wide: the first step (the address and the example) down the left, the other two beside it, so
   the reading order stays one, two, three. */
@media (min-width: 64rem) {
  .loop .steps { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 1.25rem; }
  .loop .step-ask { grid-row: span 2; }
  .loop .step { padding: 1.75rem 2rem 2rem; }
  .loop .step-num { font-size: 4.5rem; }
  .loop .step-icon { width: 60px; height: 60px; }
  .loop > h2 { font-size: 1.75rem; }
}

@media (min-width: 60rem) {
  .signin { display: grid; grid-template-columns: minmax(0, 28rem) minmax(0, 1fr); gap: 1.5rem 4rem; align-items: start; }
  .signin-lockup { grid-column: 1 / -1; margin-bottom: .5rem; }
  .signin-art { display: block; width: 100%; height: auto; max-width: 30rem; justify-self: end; margin-top: 1rem; }
}

/* The requests page (task 15) and the home page's notice of waiting requests. */
.requests { list-style: none; margin: 1rem 0; padding: 0; display: grid; gap: .75rem; }
.request { display: flex; flex-direction: column; gap: .25rem; padding: .75rem 1rem; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface); }
.request.pending { border-color: var(--accent); }
.request:focus { outline: 3px solid var(--focus); outline-offset: 2px; }
.request h2 { font-size: 1.0625rem; margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: .5rem; overflow-wrap: anywhere; }
.request h3 { font-size: 1rem; margin: .5rem 0 0; }
.request .note { font-size: 1rem; margin: 0; }
.request .changelog, .request-note { overflow-wrap: anywhere; white-space: pre-line; margin: .25rem 0; }
.decline-form textarea { width: 100%; box-sizing: border-box; font: inherit; }
.notice { padding: .75rem 1rem; margin-top: 1rem; }

/* Loading (task 17f): a page's frame draws at once, with grey-on-paper blocks shaped like its
   cards or rows where the data will go (dom.js `skeleton`), each line box the height of the real
   line, so nothing shifts when the data replaces them. Decoration only: no text, hidden from
   screen readers, which hear the container's label instead. The blocks fade in after a moment,
   so a quick answer never flashes them, then pulse gently; with reduced motion they are simply
   there. Their grey is the brand's forest, a tenth on paper. */
:root { --atoll-skeleton: color-mix(in srgb, var(--atoll-forest) 9%, var(--atoll-paper)); }
.skeleton { margin: 1rem 0; }
.sk-blocks { display: grid; gap: .75rem; }
.sk-block { display: flex; flex-direction: column; }
.sk-box { display: flex; align-items: center; height: 1.6rem; }
.sk-bar {
  display: block;
  height: .875rem;
  width: 72%;
  border-radius: var(--atoll-pill);
  background: var(--atoll-skeleton);
  animation: sk-in .2s ease-out .12s both, sk-pulse 1.8s ease-in-out .32s infinite;
}
.sk-title .sk-bar { height: 1.125rem; width: 38%; }
.sk-heading .sk-bar { height: 1.125rem; width: 45%; }
.sk-blocks > :nth-child(3n+2) .sk-title .sk-bar { width: 28%; }
.sk-blocks > :nth-child(3n) .sk-title .sk-bar { width: 46%; }
.sk-blocks > :nth-child(2n) .sk-text .sk-bar { width: 54%; }
.sk-line .sk-text:first-child .sk-bar { width: 92%; }

/* A bordered card (requests, versions, who can see a collection). */
.sk-card {
  gap: .375rem;
  padding: 1rem 1.25rem 1.125rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--atoll-surface);
}
/* A collection's card on /collections (`.collections`, `.collection`: a 44px link, a line of description). */
.skeleton-collection { margin: 1.5rem 0 1.25rem; }
.sk-collection {
  padding: .625rem 1.25rem .875rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--atoll-surface);
}
.sk-collection .sk-title { height: 44px; }
.sk-collection .sk-text { height: 1.6rem; }
/* A list row (`.people > li` and the like): a name, a smaller line under it. */
.skeleton-row { margin: 0 0 .5rem; }
.skeleton-row .sk-blocks, .skeleton-event .sk-blocks { gap: 0; }
.sk-row { gap: .125rem; padding: .875rem 0; border-bottom: 1px solid var(--line); }
.sk-row .sk-text, .sk-event .sk-text { height: 1.6rem; }
/* A row of /people with an administrator's controls: on a phone they wrap below (48px). */
.sk-person { gap: .125rem; padding: .875rem 0; border-bottom: 1px solid var(--line); }
.sk-person .sk-text { height: 1.6rem; }
.sk-person .sk-control { display: none; }
.skeleton-person { margin: 0 0 .5rem; }
.skeleton-person .sk-blocks { gap: 0; }
@media (max-width: 29.99rem) {
  .sk-person .sk-control { display: flex; height: 48px; margin-top: .5rem; }
  .sk-person .sk-control .sk-bar { height: 48px; width: 9rem; }
}
/* A line of activity (`.events li`). */
.sk-event { gap: .125rem; padding: .75rem 0; border-bottom: 1px solid var(--line); }
/* The export card on /activity (`.card` with a heading, a paragraph and the download button). */
.skeleton-export { margin: 2rem 0 0; }
.sk-export {
  padding: .5rem 1.25rem 1.25rem;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--atoll-surface);
}
.sk-export .sk-heading { height: 1.71875rem; margin: 1rem 0 .5rem; }
.sk-export .sk-text:nth-child(7) { margin-bottom: .75rem; }
.sk-export .sk-action { height: 48px; }
.sk-export .sk-action .sk-bar { height: 48px; width: 13.5rem; max-width: 100%; }
@media (min-width: 48rem) {
  .sk-export .sk-heading { height: 1.875rem; }
  /* The paragraph takes three lines here, six on a phone. */
  .sk-export .sk-text:nth-child(5), .sk-export .sk-text:nth-child(6), .sk-export .sk-text:nth-child(7) { display: none; }
  .sk-export .sk-text:nth-child(4) { margin-bottom: .75rem; }
}
h1 .sk-bar { display: inline-block; height: .8em; width: min(14rem, 60%); vertical-align: middle; }
@keyframes sk-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes sk-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .5; } }
@media (prefers-reduced-motion: reduce) {
  .sk-bar { animation: none; }
}

/* Task 17g2: joining by invite, the web half. One block, kept together at the end.
   The offer to save a passkey to someone who has just joined (save-passkey.js): a Clay-tinted
   card under the home's heading, and a slim band of the same tint above an app's frame. The
   account menu's "Confirm your email" item sits under the passkey item, in the same style. */
.save-passkey {
  margin: 0 0 1.5rem;
  padding: 1rem 1.125rem;
  border-radius: 16px;
  background: var(--atoll-clay-tint);
  color: var(--atoll-forest);
}
.save-passkey[hidden] { display: none; }
.save-passkey h2 { margin: 0 0 .375rem; font-size: 1.25rem; }
.save-passkey p { margin: 0; max-width: 40rem; line-height: 1.45; }
.save-passkey .actions { display: flex; flex-wrap: wrap; align-items: center; gap: .5rem .75rem; margin-top: .75rem; }
.save-passkey .actions button { min-height: 44px; }
.save-passkey-problem { margin-top: .5rem; font-size: 1rem; font-weight: 600; }
.save-passkey-problem:empty { display: none; }
.save-passkey.slim {
  flex: none;
  margin: 0;
  padding: .5rem var(--gutter);
  border-radius: 0;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem 1rem;
}
.save-passkey.slim[hidden] { display: none; }
.save-passkey.slim p { font-size: 1rem; }
.save-passkey.slim .save-passkey-text { flex: 1 1 16rem; }
.save-passkey.slim .actions { margin-top: 0; gap: .5rem; }
.save-passkey.slim .save-passkey-problem { flex-basis: 100%; margin-top: 0; }
.account-confirm { margin: 0 0 .375rem; }
.confirm-said { margin: .25rem .75rem 0; font-size: 1rem; color: var(--atoll-forest); }
.confirm-said:empty { display: none; }

/* Task 36b: the receiver's Island home. The account menu's "Check your email" (two lines and a
   quiet "Send it again") on Daydream's tint, where task 17g2's item was. */
.account-confirm { padding: .625rem .75rem .75rem; border-radius: 12px; background: var(--atoll-daydream-tint); }
.account-confirm p { margin: 0; overflow-wrap: anywhere; }
.confirm-title { font-weight: 600; }
.confirm-text { font-size: 1rem; line-height: 1.45; }
.account-confirm button.confirm-again { min-height: 44px; margin-top: .5rem; padding: .25rem 1.125rem; }
.account-confirm .confirm-said { margin: .5rem 0 0; }
/* The home-screen tip (home-tip.js): a Daydream card under the heading on the home; on an app's
   page a slim band of the same tint above the frame. */
.home-tip {
  margin: 0 0 1.5rem;
  padding: 1rem 1.125rem;
  border-radius: 16px;
  background: var(--atoll-daydream-tint);
  color: var(--atoll-forest);
}
.home-tip h2 { margin: 0 0 .375rem; font-size: 1.25rem; }
.home-tip p { margin: 0; max-width: 40rem; line-height: 1.45; }
.home-tip .actions { margin-top: .75rem; }
.home-tip button { min-height: 44px; }
.home-tip.slim {
  flex: none;
  margin: 0;
  padding: .5rem var(--gutter);
  border-radius: 0;
  border-bottom: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .25rem 1rem;
}
.home-tip.slim .home-tip-text { flex: 1 1 16rem; }
/* Two bands can stand above a fresh joiner's app on a phone: their buttons keep to one row, so
   the app keeps most of the height. */
.save-passkey.slim .actions button, .home-tip.slim button { padding: .25rem .75rem; }
/* A member who joined by invite, with no app yet: who will add them (in place of the steps). */
.nothing-yet {
  margin-top: 1rem;
  padding: 1.25rem 1.25rem 1.5rem;
  border: 1.5px solid var(--atoll-forest);
  border-radius: 22px;
  background: var(--atoll-new-leaf-tint);
}
.nothing-yet h2 { margin: 0 0 .375rem; }
.nothing-yet p { margin: 0; max-width: 36rem; }

/* 36c verifier: a long unbroken app name wraps inside its invite button instead of pushing About sideways at 390. */
button[data-invite-app] { overflow-wrap: anywhere; min-width: 0; max-width: 100%; white-space: normal; }

/* App icons (task 38c, app-icon.js): the image Atoll draws on the app's origin, a rounded square
   (the SVG carries its own corners), or the same face drawn here when it cannot load
   (`.icon-face`: the emoji or the initial on the colour, set through the CSSOM). */
.app-icon, .app-icon-fallback { flex: none; display: block; width: 44px; height: 44px; border-radius: 22%; box-shadow: 0 0 0 1px rgba(16, 44, 32, .22); }
.app-icon.small, .app-icon-fallback.small { width: 32px; height: 32px; }
.app-icon.large, .app-icon-fallback.large { width: 64px; height: 64px; }
.icon-face {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  overflow: hidden; border-radius: 22%; line-height: 1;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", var(--atoll-sans);
  font-size: 26px; text-decoration: none;
}
.icon-face.is-initial { font-family: var(--atoll-sans); font-weight: 600; }
.app-icon-fallback.small { font-size: 19px; }
.app-icon-fallback.large { font-size: 38px; }
/* The tile: the icon, the name taking the room, the arrow. */
.app a .app-name { flex: 1 1 auto; min-width: 0; }
.app.paused .app-icon, .app.paused .app-icon-fallback { opacity: .6; }
/* The app bar keeps one slim row: the icon sits beside the name. */
.app-bar .app-icon, .app-bar .app-icon-fallback { margin-right: -.25rem; }

/* About: the icon beside the name, and the "Icon" card: the icon now, who chose it, and a quiet
   "Change icon" that opens the picker (task 55). */
.icon-row { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem; margin: 0 0 .75rem; }
.icon-row > .note { flex: 1 1 10rem; margin: 0; }
.icon-now { width: 44px; height: 44px; box-shadow: 0 0 0 1px rgba(16, 44, 32, .22); }
.icon-form[hidden] { display: none; }
.about-head { display: flex; align-items: center; gap: 1rem; margin-bottom: .75rem; }
.about-head h1 { min-width: 0; overflow-wrap: anywhere; }
.about-icon { display: flex; flex: none; }
/* The picker: compact tiles, each radio transparent over its whole tile so a click, a tap and the
   arrow keys all work; the ring and the checked mark are drawn on the tile. */
.icon-form fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
.icon-form legend { padding: 0; font-weight: 600; }
.icon-emoji > legend { margin-bottom: .25rem; }
.emoji-group { margin-top: .75rem; }
.emoji-group > legend { font-size: 1rem; font-weight: 500; color: var(--atoll-forest-soft); margin-bottom: .25rem; }
.emoji-group > legend::first-letter { text-transform: uppercase; }
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 4px; }
.pick { position: relative; display: flex; align-items: center; justify-content: center; min-height: 44px; border: 1.5px solid transparent; border-radius: 12px; cursor: pointer; }
.pick input {
  position: absolute; inset: 0; width: 100%; height: 100%; min-height: 0; margin: 0; padding: 0;
  opacity: 0; cursor: pointer; border: 0; -webkit-appearance: none; appearance: none;
}
.pick:hover { background: var(--atoll-new-leaf-tint); }
.pick:has(input:checked) { border-color: var(--atoll-forest); background: var(--atoll-new-leaf); }
.pick:has(input:focus-visible) { outline: 3px solid var(--atoll-forest); outline-offset: 2px; }
.pick-emoji { font-size: 26px; line-height: 1; font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", var(--atoll-sans); pointer-events: none; }
.pick-initial { font-family: var(--atoll-sans); font-weight: 600; font-size: 1.25rem; }
.icon-colors { margin-top: 1.25rem; }
.icon-colors > legend { margin-bottom: .25rem; }
.color-grid { display: flex; flex-wrap: wrap; gap: .375rem; }
.pick-color { justify-content: flex-start; gap: .5rem; padding: 0 .75rem 0 .5rem; border-color: var(--atoll-edge); border-radius: var(--atoll-pill); font-weight: 500; }
.pick-color .swatch { width: 24px; height: 24px; border-radius: 50%; border: 1px solid var(--atoll-forest); pointer-events: none; }
.pick-color-name { pointer-events: none; }
/* The preview and "Save icon" stay in sight while the list scrolls past. */
.icon-save {
  position: sticky; bottom: 0; z-index: 1;
  display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1rem;
  margin: 1.25rem -1.25rem -1.25rem; padding: .75rem 1.25rem;
  border-top: 1px solid var(--line); border-radius: 0 0 18px 18px;
  background: var(--atoll-surface);
}
.icon-preview { width: 56px; height: 56px; font-size: 34px; }
.icon-save-text { flex: 1 1 6rem; min-width: 0; }
.icon-save-text p { margin: 0; }
/* A choice focused by the keyboard scrolls clear of the preview bar. */
html:has(#icon-form) { scroll-padding-bottom: 7rem; }
/* The app's initial is a letter, not an emoji: its tile is outlined so it reads as a choice. */
.pick:has(.pick-initial) { border: 1.5px dashed var(--atoll-edge); }
.pick:has(.pick-initial):has(input:checked) { border-style: solid; border-color: var(--atoll-forest); }
/* With the icon in it, the app bar's name may start narrower, so "About this app" keeps the row at 390px. */
.app-bar .app-icon + .app-title, .app-bar .app-icon-fallback + .app-title { flex-basis: 4rem; }
/* 38c verifier: a long name is two lines at most in the bar (About has it whole). */
.app-title { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }

/* Feedback (task 50): the account menu's in-page dialog (assets/feedback-dialog.js), drawn as the
   confirmation dialog, wide enough to write in and never wider than a 390px screen. */
dialog.feedback-dialog { box-sizing: border-box; width: min(32rem, calc(100vw - 2rem)); }
.feedback-dialog .feedback-title { margin: 0 0 .5rem; font-size: 1.375rem; line-height: 1.25; }
.feedback-dialog textarea { display: block; width: 100%; box-sizing: border-box; resize: vertical; margin: 0 0 .75rem; }
.feedback-dialog .feedback-count { margin: -.25rem 0 .75rem; font-size: .9375rem; }
.feedback-dialog .feedback-problem { margin: 0 0 1rem; }
.feedback-dialog .feedback-form[hidden], .feedback-dialog .feedback-sent[hidden], .feedback-dialog [data-feedback-count][hidden], .feedback-dialog .feedback-problem[hidden] { display: none; }
