/* Account — layout and typography, shared by both themes.
 *
 * Both theme sheets are always linked (index.html never swaps <link> tags,
 * only the data-theme attribute on <html>), so this file owns geometry only:
 * grids, spacing, sizing, type scale. Every place a colour would go it reads
 * a custom property instead, and retro.css / clean.css each define the whole
 * set. If a property read here is missing, a theme forgot it — this file is
 * not allowed to pick a colour on its own, and tests/css.test.js enforces
 * that by refusing any hex or rgb() in here.
 *
 * The shape is a sticky top bar, a horizontal nav below it on regular
 * widths, a bottom tab bar on compact (phone) widths, and a narrow rail on
 * short landscape screens — 44px touch targets everywhere, and safe-area
 * insets so an installed iPhone app does not tuck its tab bar under the home
 * indicator.
 */

/* ============================== Foundations ============================== */

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

html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
}

body {
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.45;
  color: var(--text);
  background-color: var(--bg);
  overflow-x: hidden;
}

h1, h2, h3, h4, p, ul, ol, dl, dd, fieldset {
  margin: 0;
}

ul, ol {
  list-style: none;
  padding: 0;
}

fieldset {
  border: 0;
  padding: 0;
  min-inline-size: 0;
}

a { color: var(--link); }

img { max-width: 100%; }

button, input, select, textarea {
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
}

/* Every control is a touch target before it is anything else. */
input, select, textarea {
  min-height: 44px;
}

textarea { resize: vertical; }

h1 { font-size: 1.6rem; line-height: 1.2; }
h2 { font-size: 1.15rem; line-height: 1.25; }
h3 { font-size: 1rem; line-height: 1.3; }

/* The shape of the ring lives here so it survives a theme switch; each theme
   supplies only --focus. Every interactive control in the markup is one of
   these tags, which is what makes one rule enough. */
:is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

/* The app toggles whole sections with the `hidden` attribute rather than a
   class, so this has to out-rank every display value either theme sets. */
[hidden] { display: none !important; }

/* The standard visually-hidden pattern: still in the accessibility tree and
   still focusable, just not painted. The :is() line is the exception that
   matters — a visually-hidden *control* is a real touch target reached
   through its own label, and a 1px box fails a 44px audit that is right to
   ask. clip-path removes it from hit-testing and from view either way, so
   the larger box costs nothing. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.sr-only:is(input, select, textarea, button) {
  width: 44px;
  height: 44px;
  margin: 0;
  pointer-events: none;
}

/* ============================== The shell ================================ */

#app {
  --topbar-h: 3.5rem;
  --navbar-h: 3.25rem;
  --tabbar-h: 3.75rem;
  --gutter: 1.25rem;
  /* The site-wide header bar (willperlak.com's /site-nav/) sits above #app,
     outside this grid. It isn't sticky, so it just scrolls away and
     #topbar's own sticky top:0 needs no change. Its height is given back
     here so a short page doesn't scroll by that much. nav.css publishes the
     height; the fallback 0 is right when it isn't loaded (run locally, the
     bar is absent). */
  --site-nav-h: var(--wp-site-nav-h, 0px);
  min-height: calc(100dvh - var(--site-nav-h));
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto auto minmax(0, 1fr);
  grid-template-areas:
    "topbar"
    "nav"
    "main";
}

#topbar {
  grid-area: topbar;
  position: sticky;
  top: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  min-height: var(--topbar-h);
  padding: 0.35rem max(var(--gutter), env(safe-area-inset-right)) 0.35rem max(var(--gutter), env(safe-area-inset-left));
  padding-top: calc(0.35rem + env(safe-area-inset-top));
}

/* The top bar's Sign out (UX-account-19), at its right end. */
#topbar-sign-out {
  margin-left: auto;
}

#brand {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: 1.4rem;
  font-weight: bold;
  letter-spacing: 0.02em;
  text-decoration: none;
}

/* ================================= Nav ====================================
 * Default shape: a horizontal bar under the topbar, full width. Compact
 * widths turn it into a bottom tab bar; short landscape screens turn it into
 * a narrow side rail. Login has no nav at all.
 */

#nav {
  grid-area: nav;
  position: sticky;
  top: var(--topbar-h);
  z-index: 25;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.15rem;
  min-height: var(--navbar-h);
  padding: 0.35rem max(var(--gutter), env(safe-area-inset-right)) 0.35rem max(var(--gutter), env(safe-area-inset-left));
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.4rem 0.85rem;
  text-decoration: none;
  font-size: 0.9rem;
}

.nav-icon {
  flex: none;
  width: 1.35rem;
  height: 1.35rem;
}

.nav-text {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon {
  flex: none;
  width: 1.25rem;
  height: 1.25rem;
  vertical-align: -0.2em;
}

/* Login is a single centred column: no nav to a screen that does not exist
   yet. */
#app[data-screen="login"] #nav {
  display: none;
}

#app[data-screen="login"] {
  grid-template-areas:
    "topbar"
    "main";
}

/* ================================= Main ================================== */

#main {
  grid-area: main;
  min-width: 0;
  padding: var(--gutter) max(var(--gutter), env(safe-area-inset-right)) 4rem max(var(--gutter), env(safe-area-inset-left));
}

.view {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  max-width: 56rem;
  min-width: 0;
}

.view-narrow {
  max-width: 30rem;
  margin-inline: auto;
  width: 100%;
}

.view-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
}

/* The big bold screen title. */
.view-title {
  font-size: 2rem;
  font-weight: bold;
  line-height: 1.1;
  letter-spacing: -0.01em;
  min-width: 0;
  overflow-wrap: anywhere;
}

.muted { font-size: 0.9rem; }

.empty {
  padding: 1.5rem 1rem;
  text-align: center;
  font-size: 0.95rem;
}

/* ================================ Panels ================================= */

.panel {
  padding: 1rem 1.1rem;
  border-radius: var(--radius);
  min-width: 0;
}

.panel > * + * { margin-top: 0.75rem; }

/* ================================ Forms =================================== */

.field-row {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
}

.field-row > label,
.field-label {
  font-size: 0.82rem;
  font-weight: bold;
  letter-spacing: 0.01em;
}

.field-row input,
.field-row select,
.field-row textarea {
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 0.55rem 0.7rem;
  border-radius: var(--radius-sm);
}

/* A password input with its Show toggle beside it (UX-account-12, RAU1-2),
   and the muted line under a field (the password rule, the profile's
   privacy note). */
.pw-field {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-width: 0;
}

.pw-field input {
  flex: 1 1 auto;
}

.pw-toggle {
  flex: none;
}

/* Pressed (the password is shown): the word stays "Show" (RAU1-2), so the
   state is a box and a fill with no underline, drawn by each theme's sheet
   (RAU1b-1); here only what is not colour. */
.pw-toggle[aria-pressed="true"] {
  text-decoration: none;
}

.field-hint {
  margin: 0;
  font-size: 0.82rem;
}

.errors {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0.6rem 0.8rem;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
}

.form-actions,
.actions,
.inline-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
}

.inline-actions { gap: 0.35rem; }

button,
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: 44px;
  min-width: 44px;
  padding: 0.5rem 1rem;
  border-radius: var(--radius-sm);
  font-size: 0.95rem;
  text-decoration: none;
  cursor: pointer;
}

.primary,
.danger {
  font-weight: bold;
}

/* A button that reads as a link: no box, no fill, just the label. */
.link-btn {
  min-height: 44px;
  padding: 0.25rem 0;
  background: none;
  border: 0;
  text-decoration: underline;
  cursor: pointer;
}

input[type="checkbox"],
input[type="radio"] {
  width: auto;
  min-height: 0;
}

/* A checkbox is a glyph, not a field: this keeps it beside its label instead
   of stretching to the field width the way a text input would. Used by
   ui/dom.js's labelledCheckbox() helper. */
.check-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 44px;
  padding: 0.25rem 0.4rem;
  border-radius: var(--radius-sm);
  min-width: 0;
}

.check-row input {
  width: auto;
  min-height: 0;
  flex: none;
  margin: 0;
}

.check-row label {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  min-height: 44px;
  cursor: pointer;
}

/* ================================ Cards ================================== */

.card-list {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.card {
  padding: 0.8rem 0.9rem;
  border-radius: var(--radius);
  min-width: 0;
}

/* ============================ People and rows ============================ */

.person-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.5rem 0.65rem;
  border-radius: var(--radius-sm);
  min-width: 0;
}

.person-name {
  font-weight: bold;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

.person-sub {
  font-size: 0.82rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* ================================ Avatars ================================ */

.avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 50%;
  overflow: hidden;
  font-weight: bold;
  font-size: 0.85rem;
  line-height: 1;
  text-transform: uppercase;
  user-select: none;
}

.avatar-small {
  width: 1.75rem;
  height: 1.75rem;
  font-size: 0.65rem;
}

.avatar-large {
  width: 6rem;
  height: 6rem;
  font-size: 2rem;
}

.avatar-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}

.avatar-initials { line-height: 1; }

/* ================================ Badges ================================= */

.badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 1.25rem;
  height: 1.25rem;
  padding: 0 0.45rem;
  border-radius: var(--radius-sm);
  font-size: 0.7rem;
  font-weight: bold;
  line-height: 1;
}

/* =============================== Invite codes ============================ */

.code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 1.05rem;
  letter-spacing: 0.06em;
}

/* =============================== Sessions ================================= */

.sess-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem 0.75rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  min-width: 0;
}

.sess-current {
  font-weight: bold;
}

/* ============================== App links ================================= */

.app-link {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 44px;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  text-decoration: none;
}

/* Home's launcher: each app's name over a one-line hint (FEAT-account-4). */
.card .app-link {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
}

.app-link .muted {
  font-weight: normal;
}

/* ================================= Toast ================================= */

.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(1.25rem + env(safe-area-inset-bottom));
  z-index: 100;
  max-width: min(92vw, 30rem);
  padding: 0.7rem 1.1rem;
  border-radius: var(--radius);
  text-align: center;
  font-weight: bold;
}

/* ============================= Compact widths ============================
 * Under 700px the top nav becomes the iOS bottom tab bar: icons over small
 * labels, fixed to the bottom, padded by the home-indicator inset, with
 * #main reserving the same height so nothing hides behind it.
 */

@media (max-width: 700px) {
  #app {
    --gutter: 1rem;
    grid-template-areas:
      "topbar"
      "main";
  }

  #nav {
    position: fixed;
    inset: auto 0 0 0;
    top: auto;
    z-index: 40;
    min-height: 0;
    flex-direction: row;
    gap: 0;
    padding: 0.2rem max(0.2rem, env(safe-area-inset-right)) 0 max(0.2rem, env(safe-area-inset-left));
    padding-bottom: env(safe-area-inset-bottom);
  }

  .nav-link {
    flex: 1 1 0;
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    min-width: 0;
    min-height: 44px;
    padding: 0.3rem 0.15rem;
  }

  .nav-text {
    font-size: 0.7rem;
    line-height: 1.1;
    max-width: 100%;
  }

  #main {
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  }

  .toast {
    bottom: calc(var(--tabbar-h) + 0.75rem + env(safe-area-inset-bottom));
  }

  .view-title { font-size: 1.6rem; }

  .panel { padding: 0.85rem 0.9rem; }
}

/* ============================ Phone landscape ============================
 * 390px of height with a keyboard up is nothing. On a wide-but-short screen
 * the nav becomes a narrow left rail of icons instead of eating a row of
 * height at the top or the bottom.
 */

@media (orientation: landscape) and (max-height: 500px) {
  #app {
    --topbar-h: 3rem;
    --navbar-h: 0px;
    grid-template-columns: calc(4.5rem + env(safe-area-inset-left, 0px)) minmax(0, 1fr);
    grid-template-areas:
      "topbar topbar"
      "nav    main";
  }

  /* The login screen has no nav, so it gets no nav column either: without
     this the form was squeezed into the 4.5rem rail column (Chromium audit,
     phone landscape, 26px-wide inputs). */
  #app[data-screen="login"] {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "topbar"
      "main";
  }

  #nav {
    position: sticky;
    top: var(--topbar-h);
    flex-direction: column;
    align-items: stretch;
    /* Stretches to its grid row, capped at one viewport under the topbar:
       the whole screen once the site-nav bar has scrolled away, and no
       taller than a short page, which then doesn't scroll for it. */
    min-height: calc(100dvh - var(--topbar-h) - var(--site-nav-h));
    max-height: calc(100dvh - var(--topbar-h));
    overflow-y: auto;
    padding: 0.4rem 0.25rem;
    padding-left: calc(0.25rem + env(safe-area-inset-left, 0px));
  }

  .nav-link {
    flex-direction: column;
    justify-content: center;
    gap: 0.1rem;
    padding: 0.35rem 0.1rem;
    text-align: center;
  }

  .nav-text {
    font-size: 0.7rem;
    line-height: 1.05;
    white-space: normal;
    overflow: visible;
  }

  #main { padding-right: max(1rem, env(safe-area-inset-right, 0px)); }
  #topbar {
    padding-left: max(1rem, env(safe-area-inset-left, 0px));
    padding-right: max(1rem, env(safe-area-inset-right, 0px));
    min-height: 3rem;
  }
  .view-title { font-size: 1.5rem; }
}

/* ================================= Motion =================================
 * Structure, not colour, so it belongs in base: every duration and easing
 * value is a token from kit/motion.css (linked before this file), and the
 * page-wide prefers-reduced-motion rule lives there once rather than being
 * restated per app. Hover effects sit under (hover: hover) so a phone tap
 * does not leave a stuck hover (5.1).
 */

:is(button, .button, a, input, select, textarea, .nav-link, .card, .person-row, .sess-row) {
  transition:
    background-color var(--duration-fast) var(--ease-standard),
    color var(--duration-fast) var(--ease-standard),
    border-color var(--duration-fast) var(--ease-standard),
    box-shadow var(--duration-fast) var(--ease-standard),
    transform var(--duration-fast) var(--ease-standard);
}

:is(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  transition: outline-color var(--duration-fast) var(--ease-standard);
}

:is(button, .button):active {
  transform: scale(0.98);
}

/* A view becoming visible (the router's show() clears `hidden`). */
.view:not([hidden]) {
  animation: wp-enter var(--duration) var(--ease-out);
}

/* An app-link is a card that is a link: it lifts on hover, laptop only. */
@media (hover: hover) {
  .app-link:hover {
    transform: translateY(-1px);
    box-shadow: var(--shadow-2);
  }
}

/* The toast's one entrance; toast.js hides it outright rather than fading it
   out, so there is no wp-toast-out trigger to hook here. */
#toast:not([hidden]) {
  animation: wp-toast-in var(--duration) var(--ease-out);
}

/* Invite cards: the code, the link and the meta line stack as rows, and the
   link wraps anywhere rather than running off a phone's edge. */
#invites-list .card {
  display: grid;
  gap: 0.35rem;
}
.invite-url {
  display: block;
  overflow-wrap: anywhere;
  word-break: break-all;
  font-size: 0.9rem;
  min-height: 44px;
  display: flex;
  align-items: center;
}
/* A badge that only labels ("This device") and must not read as a button. */
.badge-quiet {
  font-weight: normal;
}
.sess-agent {
  font-weight: bold;
}

/* "When you're free" on Home (FEAT-account-8): the vendored Scheduler editor
   (ui/schedule-editor.js) and its sched-* cards, restated from Choreing's
   layout on this app's tokens, with this app's 44px touch targets (Chores'
   are 2rem). A week is seven columns on a wide panel and
   wraps to 130px cards below 880px of panel, so a phone gets two columns. */
#schedule-editor,
.sched-grid {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  container-type: inline-size;
  min-width: 0;
}
.sched-week {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 0.4rem;
}
.sched-day {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  min-width: 0;
  min-height: 5.5rem;
  padding: 0.4rem;
  border-radius: var(--radius-sm);
}
.sched-day-label {
  font-size: 0.75rem;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sched-day-toggle {
  width: auto;
  min-height: 0;
  flex: none;
  margin: 0;
  cursor: pointer;
}
.sched-intervals {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.sched-interval {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.2rem 0.3rem;
  padding: 0.25rem 0.3rem;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
}
.sched-time-label {
  font-size: 0.68rem;
}
.sched-interval input[type="time"] {
  width: 100%;
  min-width: 0;
  max-width: none;
  min-height: 44px;
  padding: 0.15rem 0.25rem;
  font-size: 0.78rem;
}
.sched-interval .sched-remove-window {
  grid-column: 1 / -1;
}
.sched-add-window,
.sched-copy,
.sched-remove-window {
  width: 100%;
  min-width: 0;
  min-height: 44px;
  padding: 0.25rem 0.4rem;
  font-size: 0.72rem;
  border-radius: var(--radius-sm);
}
.availability-hint {
  margin: 0;
}
/* A two- or four-week grid is thousands of pixels tall on a phone, so Save
   and Clear stay at the bottom of the screen while the panel is in view
   (RAX1-7); on a compact width, above the bottom tab bar. The band's colour
   is retro.css's and clean.css's. */
#availability-panel > .form-actions {
  position: sticky;
  bottom: 0;
  z-index: 5;
  padding: 0.5rem 0;
}
/* The answer to a Save from the band is shown in the band, above the
   buttons, so it is on screen wherever the tap was (RAX1b-1). */
#availability-status,
#availability-errors {
  flex: 1 0 100%;
  margin: 0;
}
/* Empty, the status is collapsed but stays rendered: a live region that is
   display:none is out of the accessibility tree, and "Saved." appearing in it
   would not be announced (RFX3-1). The negative margin cancels the band's
   0.5rem row gap. */
#availability-status:empty {
  height: 0;
  overflow: hidden;
  margin-bottom: -0.5rem;
}
#availability-errors {
  max-height: 30vh;
  overflow-y: auto;
}
@media (max-width: 700px) {
  #availability-panel > .form-actions {
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom));
  }
}
@container (max-width: 880px) {
  .sched-week { grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); }
  /* A narrow card stacks each label over its time, so "06:00 PM" fits. */
  .sched-interval { grid-template-columns: minmax(0, 1fr); }
}

/* Agent access: the Agents page (A5) and, later, the consent view (A3b).
   Layout only, on tokens; the colours are retro.css's and clean.css's. */
.scope-group { display: grid; gap: 0.25rem; margin: 0 0 0.75rem; min-width: 0; }
.scope-group-name { font-weight: 600; }
/* A choice row: the label is the 44px target, the box sits beside its text. */
.scope-row {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 44px;
  padding: 0.25rem 0.4rem;
  border-radius: var(--radius-sm);
  min-width: 0;
  cursor: pointer;
}
.scope-row input { flex: none; margin: 0; }
.scope-row span { min-width: 0; overflow-wrap: anywhere; }
/* The "not verified" flag beside a client's name (its border and colour are
   .badge-quiet's): a small outlined label, never a button. */
/* Consent's signed-out sentence sits in the view header (beside nothing):
   its own full line under the title. */
#consent-signed-out { flex-basis: 100%; }
.client-flag {
  display: inline-block;
  padding: 0.05rem 0.45rem;
  border-radius: var(--radius-sm);
  font-size: 0.75em;
  font-weight: normal;
  vertical-align: middle;
}
/* Scrolled to after Make key: clear of the sticky top bar and nav. */
#key-created {
  scroll-margin-top: calc(var(--topbar-h) + var(--navbar-h) + 0.75rem);
}
/* The client's claimed home site, beside the flag, quieter than the name. */
.key-value {
  display: block;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius-sm);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.95rem;
  overflow-wrap: anywhere;
  word-break: break-all;
  user-select: all;
}
/* Connection and key cards stack their lines, like the invite cards. */
#connections-list .card,
#keys-list .card {
  display: grid;
  gap: 0.3rem;
  min-width: 0;
}
#connections-list .card > *,
#keys-list .card > * { min-width: 0; overflow-wrap: anywhere; }
#key-form fieldset + fieldset { margin-top: 0.75rem; }
/* "Recent activity" on each card (FEAT-account-13): closed by default; the
   summary keeps its disclosure marker and is a 44px touch target. */
.activity > summary {
  padding: 0.75rem 0;
  line-height: 1.25rem;
  cursor: pointer;
}
.activity-list {
  margin: 0;
  padding: 0 0 0.25rem 1.1rem;
  list-style: none;
  display: grid;
  gap: 0.2rem;
  font-size: 0.9rem;
}

/* ===================== Friend link QR code (FEAT-account-7) ================
 * The inline SVG from js/ui/qr.js: 200px square, never wider than its panel,
 * centred. Black on white in every theme and scheme (RAF2-3), set by
 * retro.css and clean.css since base.css has no colours.
 */
.qr {
  display: flex;
  justify-content: center;
}
.qr svg {
  display: block;
  width: 200px;
  max-width: 100%;
  height: auto;
  aspect-ratio: 1;
}

/* ================= New-device sign-in notice (FEAT-account-10) ============ */
.notice .sess-row {
  display: grid;
  gap: 0.35rem;
}

/* A friend's shared email and phone (FEAT-account-11): its own line under
   the name, after the row's actions, aligned past the avatar. Rows without
   one keep their single line. */
.person-row:has(.contact-line) {
  flex-wrap: wrap;
}

.contact-line {
  order: 10;
  flex-basis: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 0 1rem;
  padding-left: 3.2rem;
  font-size: 0.82rem;
  min-width: 0;
}

/* Each link is a 44px tap target, like every other control. */
.contact-line a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  min-width: 44px;
  overflow-wrap: anywhere;
}
