/* ==========================================================================
   Family Orbit - the project's own visual layer.

   Bootstrap supplies the responsive grid, form reset and accessible component
   behaviour. Everything below exists so the result does not read as a stock
   Bootstrap dashboard: an orbit-and-bubble mark, a scatter of identity icons,
   a wavy header edge, name bubbles and a few drifting specks.

   Three rules hold everywhere in this file:

   1. The composition is free-flowing; the controls are not. Every interactive
      element keeps a predictable position, a visible focus ring, a real label
      and a 44x44px minimum hit area, no matter how the decoration is arranged.
   2. Decorative shapes are inert. They are pointer-events:none and marked
      aria-hidden in the markup, so nothing that drifts can be mistaken for a
      button.
   3. Crisp, not soft. Surfaces get a hairline edge and a tight shadow rather
      than a wide blur; nothing that carries text is rotated or scaled at
      rest, because a fractional transform makes the browser render the text
      blurry. Playfulness comes from shape and colour, not haze.
   ========================================================================== */

:root {
  /* Colour tokens, per docs/architecture.md section 8. */
  --fo-primary: #6d5ce7;
  --fo-primary-dark: #5142c7;
  --fo-secondary: #3b82f6;
  --fo-sky: #dceeff;
  --fo-lavender: #eeeafe;
  --fo-canvas: #f7f8fc;
  --fo-surface: #ffffff;
  --fo-text: #20243a;
  --fo-muted: #5c637a;
  --fo-success: #1f9d78;
  --fo-danger: #d6455d;

  /* Text-bearing variants of the three accent tokens above.
     The palette in docs/architecture.md section 8 is the brand palette and
     stays exactly as documented - but Secondary, Success and Danger do not
     reach 4.5:1 against white, and the document itself says an accent must
     pass contrast wherever it carries text or state. These deeper shades are
     used on any surface with words on it; the originals stay for fills,
     borders and decoration. Ratios are checked in
     tests/security/test_colour_contrast.py. */
  --fo-secondary-deep: #0d64f4;
  --fo-success-deep: #167056;
  --fo-danger-deep: #d12e49;

  /* Restrained accents. Decorative unless they carry state, and never the
     only channel through which state is communicated. */
  --fo-aqua: #5fd2d2;
  --fo-coral: #ff8f6b;
  --fo-sunny: #ffd166;

  /* Edges. A hairline is what makes a white card on a near-white page read
     as a sharp object rather than a smudge. */
  --fo-line: #e3e5ef;
  --fo-line-strong: #cfd3e3;

  --fo-radius-sm: 8px;
  --fo-radius: 12px;
  --fo-radius-lg: 18px;
  --fo-radius-pill: 999px;

  --fo-shadow-soft: 0 1px 2px rgba(32, 36, 58, 0.06), 0 2px 6px rgba(32, 36, 58, 0.04);
  --fo-shadow-lift: 0 1px 2px rgba(81, 66, 199, 0.18), 0 4px 12px rgba(81, 66, 199, 0.18);
  --fo-focus: 0 0 0 3px rgba(109, 92, 231, 0.3);

  --fo-touch: 44px;

  --fo-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans", sans-serif;
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

.fo-body {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  margin: 0;
  font-family: var(--fo-font);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--fo-text);
  background: var(--fo-canvas);
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

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

.fo-skip-link {
  position: absolute;
  top: -100px;
  left: 16px;
  z-index: 100;
  padding: 12px 20px;
  color: #fff;
  background: var(--fo-primary-dark);
  border-radius: 0 0 var(--fo-radius-sm) var(--fo-radius-sm);
  text-decoration: none;
}

.fo-skip-link:focus {
  top: 0;
}

a {
  color: var(--fo-primary-dark);
  text-underline-offset: 3px;
}

a:hover { color: var(--fo-primary); }

/* One focus treatment for everything interactive, so a keyboard user is never
   left guessing where they are inside a playful layout. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--fo-primary-dark);
  outline-offset: 3px;
  border-radius: var(--fo-radius-sm);
}

.fo-identity__input:focus-visible + .fo-identity,
.fo-bubble__input:focus-visible + .fo-bubble {
  outline: 3px solid var(--fo-primary-dark);
  outline-offset: 4px;
}

/* --------------------------------------------------------------------------
   Decorative sky: blobs, orbits and drifting specks.
   Kept faint and hard-edged - no blur filter - so the page behind the
   content reads as a quiet pattern rather than a haze.
   -------------------------------------------------------------------------- */

.fo-sky {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.fo-blob {
  position: absolute;
  display: block;
  opacity: 0.1;
}

.fo-blob--one {
  top: 30%;
  left: -160px;
  width: 340px;
  height: 320px;
  background: var(--fo-primary);
  border-radius: 58% 42% 38% 62% / 52% 46% 54% 48%;
  animation: fo-drift-a 26s ease-in-out infinite;
}

.fo-blob--two {
  right: -180px;
  bottom: -160px;
  width: 420px;
  height: 380px;
  background: var(--fo-secondary);
  border-radius: 44% 56% 62% 38% / 48% 58% 42% 52%;
  opacity: 0.08;
  animation: fo-drift-b 32s ease-in-out infinite;
}

.fo-blob--three {
  top: 18%;
  right: 6%;
  width: 120px;
  height: 112px;
  background: var(--fo-aqua);
  border-radius: 62% 38% 46% 54% / 40% 56% 44% 60%;
  opacity: 0.14;
  animation: fo-drift-a 22s ease-in-out infinite reverse;
}

.fo-orbit {
  position: absolute;
  display: block;
  border: 1px dashed rgba(109, 92, 231, 0.2);
  border-radius: 50%;
}

.fo-orbit--wide {
  top: 10%;
  left: 50%;
  width: 760px;
  height: 760px;
  margin-left: -380px;
  animation: fo-spin 120s linear infinite;
}

.fo-orbit--tight {
  bottom: 4%;
  left: 6%;
  width: 260px;
  height: 260px;
  border-color: rgba(59, 130, 246, 0.18);
  animation: fo-spin 80s linear infinite reverse;
}

.fo-speck {
  position: absolute;
  display: block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  opacity: 0.8;
}

.fo-speck--a { top: 22%; left: 12%; background: var(--fo-sunny); animation: fo-bob 7s ease-in-out infinite; }
.fo-speck--b { top: 64%; left: 6%;  background: var(--fo-coral); animation: fo-bob 9s ease-in-out infinite 1s; }
.fo-speck--c { top: 34%; right: 10%; background: var(--fo-aqua);  animation: fo-bob 8s ease-in-out infinite .5s; }
.fo-speck--d { bottom: 16%; right: 20%; background: var(--fo-primary); animation: fo-bob 11s ease-in-out infinite 2s; }

@keyframes fo-drift-a {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50% { transform: translate3d(24px, 28px, 0) rotate(8deg); }
}

@keyframes fo-drift-b {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  50% { transform: translate3d(-30px, -22px, 0) rotate(-6deg); }
}

@keyframes fo-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

@keyframes fo-bob {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-12px); }
}

/* --------------------------------------------------------------------------
   Header and layout
   -------------------------------------------------------------------------- */

.fo-header {
  position: relative;
  z-index: 2;
  background: linear-gradient(110deg, var(--fo-primary-dark) 0%, var(--fo-primary) 45%, var(--fo-secondary-deep) 100%);
  color: #fff;
}

.fo-header__inner {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
  align-items: center;
  justify-content: space-between;
  max-width: 1100px;
  margin: 0 auto;
  padding: 14px 16px 4px;
}

.fo-wave {
  display: block;
  width: 100%;
  height: 22px;
  margin-bottom: -1px;
  fill: var(--fo-canvas);
}

.fo-mark {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  min-height: var(--fo-touch);
  color: #fff;
  text-decoration: none;
}

.fo-mark:hover { color: #fff; }

.fo-mark__logo {
  display: block;
  width: 40px;
  height: 40px;
  background: url("../img/logo.svg") center / cover no-repeat;
  border-radius: 10px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35), 0 2px 6px rgba(20, 16, 70, 0.25);
}

.fo-mark__name {
  display: block;
  font-size: 1.2rem;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.fo-mark__sub {
  display: block;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  opacity: 0.9;
}

/* The signed-in cluster: who, what kind of session, and the ways out. One
   tidy row of equal-height pieces rather than a wrap of mismatched pills. */
.fo-session {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: flex-end;
}

.fo-session__who {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  margin: 0 6px 0 0;
  line-height: 1.15;
}

.fo-session__who > .bi {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  font-size: 0.95rem;
  background: rgba(255, 255, 255, 0.16);
  border-radius: 50%;
}

.fo-session__lines { display: flex; flex-direction: column; }
.fo-session__name { font-weight: 700; }
.fo-session__scope { font-size: 0.75rem; font-weight: 600; opacity: 0.88; }
.fo-session__form { margin: 0; }

/* A header button: an outlined white control that sits on the gradient
   without competing with it. */
.fo-headbtn {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  min-width: var(--fo-touch);
  min-height: var(--fo-touch);
  padding: 0 14px;
  color: #fff;
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  text-decoration: none;
  background: rgba(255, 255, 255, 0.12);
  border: 1px solid rgba(255, 255, 255, 0.4);
  border-radius: var(--fo-radius);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}

.fo-headbtn:hover { color: #fff; background: rgba(255, 255, 255, 0.24); border-color: #fff; }
.fo-headbtn:focus-visible { outline-color: #fff; }

.fo-main {
  position: relative;
  z-index: 1;
  flex: 1 0 auto;
}

.fo-canvas {
  max-width: 1100px;
  margin: 0 auto;
  padding: 24px 16px 56px;
}

.fo-canvas--narrow { max-width: 560px; }
.fo-canvas--wide { max-width: 1100px; }

.fo-footer {
  position: relative;
  z-index: 1;
  padding: 0 16px 28px;
  text-align: center;
}

.fo-footer__note {
  margin: 0;
  color: var(--fo-muted);
  font-size: 0.85rem;
}

.fo-headline {
  margin: 8px 0 22px;
  font-size: clamp(1.75rem, 4.5vw, 2.5rem);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.025em;
}

.fo-headline__small {
  display: block;
  margin-bottom: 6px;
  /* Small uppercase text, so it takes the darker shade of the same colour.
     Primary itself is 4.56:1 here - passing, but with nothing to spare. */
  color: var(--fo-primary-dark);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Status messages. State is never colour alone: each carries an icon and
   words, so it survives a colour-vision difference and a greyscale print.
   -------------------------------------------------------------------------- */

.fo-status { min-height: 1px; }

.fo-alert {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  align-items: flex-start;
  margin: 0 0 18px;
  padding: 12px 16px;
  font-weight: 600;
  line-height: 1.45;
  border: 1px solid transparent;
  border-radius: var(--fo-radius);
}

/* Icon in its own fixed column, words beside it - never the icon alone on
   one line and the sentence on the next. */
.fo-alert > .bi { flex: 0 0 auto; margin-top: 1px; }
.fo-alert > span:not(.fo-alert__detail) { flex: 1 1 0; min-width: 0; }

.fo-alert--success { color: #12684f; background: #dbf5ec; border-color: #b9e8d7; }
.fo-alert--error { color: #8d1e33; background: #ffe2e7; border-color: #f8c4ce; }
.fo-alert--info { color: #23417c; background: #dceeff; border-color: #bcdcfb; }

.fo-alert__detail {
  flex-basis: 100%;
  padding-left: 26px;
  font-weight: 400;
  font-size: 0.9rem;
}

.fo-empty {
  margin: 0;
  padding: 18px;
  color: var(--fo-muted);
  text-align: center;
}

/* --------------------------------------------------------------------------
   Quick Send steps
   -------------------------------------------------------------------------- */

.fo-step { margin-bottom: 32px; }

.fo-step__heading {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: 0 0 14px;
  font-size: 1.15rem;
  font-weight: 750;
  letter-spacing: -0.01em;
}

.fo-step__number {
  display: grid;
  flex: 0 0 auto;
  place-items: center;
  width: 28px;
  height: 28px;
  color: #fff;
  font-size: 0.9rem;
  font-weight: 800;
  background: var(--fo-primary);
  border-radius: 50%;
}

/* Recipient bubbles. Each sits at a slightly different whole-pixel offset so
   the row reads as a drift of name balloons rather than a row of buttons,
   while the DOM order, tab order and hit areas stay conventional. */
.fo-bubbles {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 0;
  padding: 6px 0;
  list-style: none;
}

.fo-bubbles__item--0 { transform: translateY(-4px); }
.fo-bubbles__item--1 { transform: translateY(5px); }
.fo-bubbles__item--2 { transform: translateY(-1px); }
.fo-bubbles__item--3 { transform: translateY(6px); }
.fo-bubbles__item--4 { transform: translateY(-5px); }

.fo-bubble__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.fo-bubble {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  min-height: var(--fo-touch);
  padding: 8px 20px;
  color: var(--fo-text);
  font-weight: 700;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius-pill);
  box-shadow: var(--fo-shadow-soft);
  cursor: pointer;
  transition: border-color 120ms ease, box-shadow 120ms ease, background 120ms ease;
}

.fo-bubble:hover { border-color: var(--fo-primary); }

.fo-bubble--everyone { background: var(--fo-sky); border-color: #bcdcfb; }

/* Selected state uses colour, a border, a shadow and a tick - not colour alone. */
.fo-bubble__input:checked + .fo-bubble {
  color: #fff;
  background: var(--fo-primary);
  border-color: var(--fo-primary-dark);
  box-shadow: var(--fo-shadow-lift);
}

.fo-bubble__input:checked + .fo-bubble::after {
  content: "\2713";
  font-weight: 800;
}

/* The composer card. */
.fo-cloud {
  position: relative;
  padding: 16px;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
  box-shadow: var(--fo-shadow-soft);
}

.fo-cloud__field {
  display: block;
  width: 100%;
  padding: 12px 14px;
  font-size: 1.05rem;
  line-height: 1.5;
  color: var(--fo-text);
  background: var(--fo-canvas);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius);
  resize: vertical;
}

.fo-cloud__field:focus {
  background: var(--fo-surface);
  border-color: var(--fo-primary);
  box-shadow: var(--fo-focus);
  outline: none;
}

.fo-cloud__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 12px;
  justify-content: space-between;
}

.fo-cloud__help,
.fo-cloud__count {
  margin: 10px 0 0;
  color: var(--fo-muted);
  font-size: 0.85rem;
}

.fo-cloud__count { text-align: right; }
.fo-cloud__count.is-tight { color: var(--fo-danger-deep); font-weight: 700; }

/* The identity constellation. Twelve circles, each nudged to a different
   whole-pixel offset so the group scatters, with DOM order left intact so
   keyboard and screen-reader traversal stays a simple 1-to-12 sweep. */
.fo-constellation {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin: 0;
  padding: 14px 0;
  list-style: none;
}

.fo-constellation__item--1  { transform: translateY(-10px); }
.fo-constellation__item--2  { transform: translateY(4px); }
.fo-constellation__item--3  { transform: translateY(-3px); }
.fo-constellation__item--4  { transform: translateY(10px); }
.fo-constellation__item--5  { transform: translateY(-7px); }
.fo-constellation__item--6  { transform: translateY(3px); }
.fo-constellation__item--7  { transform: translateY(9px); }
.fo-constellation__item--8  { transform: translateY(-6px); }
.fo-constellation__item--9  { transform: translateY(7px); }
.fo-constellation__item--10 { transform: translateY(-9px); }
.fo-constellation__item--11 { transform: translateY(2px); }
.fo-constellation__item--12 { transform: translateY(-4px); }

.fo-identity__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

.fo-identity {
  display: grid;
  place-items: center;
  width: 64px;
  height: 64px;
  font-size: 1.6rem;
  color: var(--fo-primary);
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: 50%;
  box-shadow: var(--fo-shadow-soft);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease, color 120ms ease, box-shadow 120ms ease;
}

.fo-identity:hover { border-color: var(--fo-primary); box-shadow: var(--fo-focus); }

.fo-identity__input:checked + .fo-identity {
  color: #fff;
  background: linear-gradient(140deg, var(--fo-primary), var(--fo-secondary-deep));
  border-color: var(--fo-primary-dark);
  box-shadow: var(--fo-shadow-lift);
  animation: fo-pick 280ms ease;
}

.fo-identity--static {
  display: inline-grid;
  width: 36px;
  height: 36px;
  margin-right: 8px;
  font-size: 1rem;
  vertical-align: middle;
  box-shadow: none;
  cursor: default;
}

.fo-identity--static:hover { border-color: var(--fo-line-strong); box-shadow: none; }

/* The compact grid on the admin and sign-in forms: a tidy, even grid, no
   scatter. The offsets are for the homepage, where there is room for them;
   in a form they push icons into the text above and below. */
.fo-constellation--compact {
  justify-content: flex-start;
  gap: 10px;
  padding: 4px 0;
}

.fo-constellation--compact .fo-constellation__item { transform: none; }
.fo-constellation--compact .fo-identity { width: 52px; height: 52px; font-size: 1.3rem; }

@keyframes fo-pick {
  0% { transform: scale(1); }
  45% { transform: scale(1.12); }
  100% { transform: scale(1); }
}

/* PIN entry. One large native field: on a phone or tablet inputmode=numeric
   brings up the device's own number pad, which is bigger and more familiar
   than anything drawn on the page. */
.fo-pin {
  max-width: 320px;
  margin: 0 auto;
  padding: 20px;
  text-align: center;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
  box-shadow: var(--fo-shadow-soft);
}

.fo-pin__field {
  display: block;
  width: 100%;
  max-width: 220px;
  min-height: 60px;
  margin: 0 auto;
  padding: 10px 12px 10px calc(12px + 0.6em);
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: 0.6em;
  text-align: center;
  color: var(--fo-text);
  background: var(--fo-canvas);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius);
}

.fo-pin__field:focus {
  background: var(--fo-surface);
  border-color: var(--fo-primary);
  box-shadow: var(--fo-focus);
  outline: none;
}

.fo-pin__help {
  margin: 10px 0 0;
  color: var(--fo-muted);
  font-size: 0.85rem;
}

/* The send action. Large, high contrast, and always in the same place. */
.fo-send { margin-top: 8px; text-align: center; }

.fo-send__button {
  display: inline-flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  min-width: 220px;
  min-height: 56px;
  padding: 14px 36px;
  color: #fff;
  font-size: 1.15rem;
  font-weight: 800;
  line-height: 1.2;
  background: linear-gradient(110deg, var(--fo-primary-dark), var(--fo-secondary-deep));
  border: 1px solid var(--fo-primary-dark);
  border-radius: var(--fo-radius-pill);
  box-shadow: var(--fo-shadow-lift);
  cursor: pointer;
  transition: transform 120ms ease, box-shadow 120ms ease;
}

.fo-send__button:hover { transform: translateY(-2px); box-shadow: 0 2px 4px rgba(81, 66, 199, 0.2), 0 8px 18px rgba(81, 66, 199, 0.24); }
.fo-send__button:active { transform: translateY(0); }

.fo-secondary {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  margin-top: 36px;
}

.fo-secondary__link {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  min-height: var(--fo-touch);
  padding: 0 18px;
  color: var(--fo-muted);
  font-weight: 600;
  text-decoration: none;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius);
}

.fo-secondary__link:hover { color: var(--fo-primary-dark); border-color: var(--fo-primary); }

.fo-flow__footnote {
  margin: 18px 0 0;
  color: var(--fo-muted);
  font-size: 0.9rem;
  text-align: center;
}

/* --------------------------------------------------------------------------
   Panels, buttons and forms
   -------------------------------------------------------------------------- */

.fo-panel {
  margin-bottom: 20px;
  padding: 28px;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
  box-shadow: var(--fo-shadow-soft);
}

.fo-panel--centre { text-align: center; }
.fo-panel--wide { padding: 24px; }

.fo-panel--warning {
  border-top: 4px solid var(--fo-danger);
}

.fo-panel__head {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}

.fo-panel__head .fo-panel__title { margin: 0; }

.fo-panel__icon {
  margin: 0 0 8px;
  font-size: 2.2rem;
  line-height: 1;
  color: var(--fo-danger-deep);
}

.fo-panel__title {
  margin: 0 0 12px;
  font-size: 1.4rem;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -0.015em;
}

.fo-panel__title--sub { margin-top: 28px; font-size: 1.1rem; letter-spacing: -0.01em; }
.fo-panel > .fo-panel__title--sub:first-child { margin-top: 0; }
.fo-panel__body { margin: 0 0 22px; font-size: 1.02rem; line-height: 1.6; }
.fo-panel__note { margin: 0 0 18px; color: var(--fo-muted); font-size: 0.9rem; line-height: 1.55; }
.fo-panel__alt { margin: 16px 0 0; }

/* Buttons. One shape, one height and one set of weights everywhere, so a
   button on the sign-in page and a button on the admin page are visibly the
   same object. Text may wrap onto a second line on a narrow phone, and when
   it does it stays centred inside the button rather than spilling out. */
.fo-button {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  min-height: var(--fo-touch);
  padding: 10px 20px;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  vertical-align: middle;
  border: 1px solid transparent;
  border-radius: var(--fo-radius);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.fo-button > .bi { flex: 0 0 auto; }

.fo-button--primary {
  color: #fff;
  background: var(--fo-primary);
  border-color: var(--fo-primary-dark);
  box-shadow: 0 1px 2px rgba(81, 66, 199, 0.25);
}

.fo-button--primary:hover { background: var(--fo-primary-dark); color: #fff; }

.fo-button--danger { color: #fff; background: var(--fo-danger-deep); border-color: #b8394e; }
.fo-button--danger:hover { color: #fff; background: #b8394e; }

.fo-button--quiet {
  color: var(--fo-primary-dark);
  background: var(--fo-lavender);
  border-color: #dcd5fb;
}

.fo-button--quiet:hover { color: var(--fo-primary-dark); background: #e3ddfd; border-color: #c9bff8; }

/* The secondary action beside a primary one: present, plainly a button, but
   quieter so the primary is never in doubt. */
.fo-button--ghost {
  color: var(--fo-primary-dark);
  background: var(--fo-surface);
  border-color: var(--fo-line-strong);
}

.fo-button--ghost:hover { color: var(--fo-primary-dark); background: var(--fo-canvas); border-color: var(--fo-primary); }

.fo-button--block { width: 100%; }
.fo-button--small { min-height: var(--fo-touch); padding: 6px 14px; font-size: 0.9rem; }

/* A group of actions. Stacked full-width by default - the sign-in pages,
   where the choice is "this, or the other thing" - and as a row in a form. */
.fo-actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 24px;
}

.fo-actions > form { margin: 0; }

.fo-actions--row {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
}

.fo-field { margin-bottom: 20px; }

.fo-field__label {
  display: block;
  margin-bottom: 6px;
  font-weight: 700;
}

.fo-field__input {
  display: block;
  width: 100%;
  min-height: var(--fo-touch);
  padding: 10px 12px;
  font-size: 1rem;
  color: var(--fo-text);
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius);
}

.fo-field__input:focus {
  border-color: var(--fo-primary);
  box-shadow: var(--fo-focus);
  outline: none;
}

.fo-field__help { display: block; margin: 6px 0 0; color: var(--fo-muted); font-size: 0.85rem; font-weight: 400; }

.fo-fieldset { margin: 0 0 22px; padding: 0; border: 0; }
.fo-fieldset__legend { margin-bottom: 8px; font-size: 1rem; font-weight: 700; }
.fo-fieldset > .fo-field__help { margin: 0 0 12px; }

/* A checkbox with its label and explanation beside it, aligned to the
   first line of text rather than floating against the middle. */
.fo-check {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.fo-check__input {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin: 1px 0 0;
  accent-color: var(--fo-primary);
  cursor: pointer;
}

.fo-check__label { font-weight: 700; cursor: pointer; }

/* One action on one value: label above, the field and its button side by
   side with a gap between, help underneath. On a phone the button drops
   below the field rather than squeezing it. */
.fo-inline-form {
  padding: 18px 0;
  border-top: 1px solid var(--fo-line);
}

.fo-inline-form:last-child { padding-bottom: 0; }

.fo-inline-form__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: stretch;
}

.fo-inline-form__row > .fo-field__input { flex: 1 1 240px; width: auto; }
.fo-inline-form__row > .fo-button { flex: 0 0 auto; }

/* --------------------------------------------------------------------------
   Conversations
   -------------------------------------------------------------------------- */

.fo-people { margin-bottom: 20px; }

.fo-people__heading {
  margin: 0 0 10px;
  color: var(--fo-muted);
  font-size: 0.8rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.fo-people__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.fo-people__link {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  min-height: var(--fo-touch);
  padding: 0 18px;
  color: var(--fo-text);
  font-weight: 700;
  text-decoration: none;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius-pill);
  transition: border-color 120ms ease, color 120ms ease;
}

.fo-people__link:hover { color: var(--fo-primary-dark); border-color: var(--fo-primary); }
.fo-people__link--everyone { background: var(--fo-sky); border-color: #bcdcfb; }

/* The conversation on screen, marked by the server with aria-current. */
.fo-people__link[aria-current="page"] {
  color: #fff;
  background: var(--fo-primary);
  border-color: var(--fo-primary-dark);
}

.fo-people__link[aria-current="page"] .fo-people__note { color: #fff; }

/* Unread carries a starburst, a count and screen-reader words, so the state
   survives a colour-vision difference and never depends on the fill alone. */
.fo-people__link--unread {
  border: 2px solid var(--fo-primary);
  font-weight: 800;
}

.fo-unread {
  display: inline-flex;
  gap: 4px;
  align-items: center;
  margin-left: 2px;
  padding: 2px 9px 2px 6px;
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
  background: var(--fo-secondary-deep);
  border-radius: var(--fo-radius-pill);
}

.fo-unread__burst {
  font-size: 0.78rem;
  animation: fo-twinkle 2.4s ease-in-out infinite;
}

@keyframes fo-twinkle {
  0%, 100% { transform: rotate(0deg) scale(1); }
  50% { transform: rotate(45deg) scale(1.15); }
}

/* Notices inside a conversation: why this view behaves differently. Always
   an icon plus a sentence, never a colour on its own. */
.fo-notice {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
  justify-content: center;
  margin: 0 0 16px;
  padding: 10px 16px;
  color: var(--fo-muted);
  font-size: 0.9rem;
  background: var(--fo-canvas);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius);
}

.fo-notice--history { color: #7a4a10; background: #fff1d6; border-color: #f6dca8; }
.fo-notice--closed { color: #5c6178; background: #e9ebf3; }

.fo-earlier { margin: 0 0 16px; text-align: center; }

.fo-people__note {
  margin-left: 2px;
  color: var(--fo-muted);
  font-size: 0.75rem;
  font-weight: 600;
}

.fo-people__link--inactive { opacity: 0.75; }

.fo-thread {
  padding: 20px;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
  box-shadow: var(--fo-shadow-soft);
}

.fo-thread--empty { text-align: center; }

.fo-thread__prompt {
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: center;
  margin: 0;
  padding: 40px 0;
  color: var(--fo-muted);
}

.fo-thread__prompt > .bi { font-size: 2rem; color: var(--fo-primary); }

.fo-thread__heading {
  display: flex;
  gap: 10px;
  align-items: center;
  margin: -20px -20px 16px;
  padding: 14px 20px;
  font-size: 1.15rem;
  font-weight: 800;
  border-bottom: 1px solid var(--fo-line);
}

.fo-thread__list {
  margin: 0 0 16px;
  padding: 4px 2px;
  list-style: none;
  max-height: 56vh;
  overflow-y: auto;
}

.fo-thread__empty { color: var(--fo-muted); text-align: center; }

.fo-msg {
  position: relative;
  width: fit-content;
  min-width: 180px;
  max-width: 78%;
  margin-bottom: 10px;
  /* Room on the right for the delete button, so it never sits on the text. */
  padding: 10px 52px 10px 14px;
  border: 1px solid transparent;
  border-radius: var(--fo-radius-lg);
}

.fo-msg--mine {
  margin-left: auto;
  background: var(--fo-lavender);
  border-color: #dcd5fb;
  border-bottom-right-radius: 4px;
}

.fo-msg--theirs {
  margin-right: auto;
  background: var(--fo-sky);
  border-color: #c4e0fc;
  border-bottom-left-radius: 4px;
}

.fo-msg--deleted { background: #f1f2f7; border-color: var(--fo-line); font-style: italic; color: var(--fo-muted); padding-right: 14px; }

.fo-msg__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 10px;
  align-items: baseline;
  margin: 0 0 2px;
  font-size: 0.78rem;
  color: var(--fo-muted);
}

.fo-msg__sender { font-weight: 700; color: var(--fo-text); }

/* Message text. pre-wrap preserves the sender's own line breaks, and
   overflow-wrap keeps a long unbroken URL - which is never a link - from
   pushing the layout sideways. */
.fo-msg__body {
  margin: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Delivery state on your own messages. Quiet by design: useful when you go
   looking for it, not competing with the message itself. */
.fo-msg__status {
  display: flex;
  gap: 4px;
  align-items: center;
  justify-content: flex-end;
  margin: 4px -38px 0 0;
  color: var(--fo-muted);
  font-size: 0.72rem;
  font-weight: 700;
}

.fo-msg__status--read { color: var(--fo-success-deep); }

.fo-msg__delete { position: absolute; top: 0; right: 0; }

.fo-msg__delete-button {
  display: grid;
  place-items: center;
  width: var(--fo-touch);
  height: var(--fo-touch);
  color: var(--fo-muted);
  background: transparent;
  border: none;
  border-radius: var(--fo-radius);
  cursor: pointer;
}

.fo-msg__delete-button:hover { color: var(--fo-danger-deep); background: rgba(214, 69, 93, 0.1); }

/* The composer stays docked at the bottom of the thread so sending is always
   in the same place, however playful the rest of the page is. Field and
   button share a row; the count sits underneath. */
.fo-composer {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px 10px;
  align-items: end;
  margin: 0 -20px -20px;
  padding: 14px 20px 16px;
  background: var(--fo-canvas);
  border-top: 1px solid var(--fo-line);
  border-radius: 0 0 var(--fo-radius-lg) var(--fo-radius-lg);
}

.fo-composer__field {
  grid-column: 1;
  width: 100%;
  min-height: var(--fo-touch);
  padding: 10px 12px;
  font-size: 1rem;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line-strong);
  border-radius: var(--fo-radius);
  resize: vertical;
}

.fo-composer__field:focus { border-color: var(--fo-primary); box-shadow: var(--fo-focus); outline: none; }
.fo-composer__count { grid-column: 1 / -1; grid-row: 3; margin: 0; color: var(--fo-muted); font-size: 0.8rem; }
.fo-composer__count.is-tight { color: var(--fo-danger-deep); font-weight: 700; }

.fo-composer__error {
  grid-column: 1 / -1;
  grid-row: 2;
  padding: 8px 12px;
  color: #8d1e33;
  font-weight: 600;
  background: #ffe2e7;
  border: 1px solid #f8c4ce;
  border-radius: var(--fo-radius-sm);
}

.fo-composer__error[hidden] { display: none; }

.fo-composer__send {
  grid-column: 2;
  grid-row: 1;
  display: inline-flex;
  gap: 8px;
  align-items: center;
  justify-content: center;
  min-height: var(--fo-touch);
  padding: 0 22px;
  color: #fff;
  font-weight: 800;
  white-space: nowrap;
  background: linear-gradient(110deg, var(--fo-primary-dark), var(--fo-secondary-deep));
  border: 1px solid var(--fo-primary-dark);
  border-radius: var(--fo-radius);
  cursor: pointer;
}

.fo-expiry {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-bottom: 18px;
  padding: 10px 16px;
  font-weight: 600;
  color: #7a4a10;
  background: #fff1d6;
  border: 1px solid #f6dca8;
  border-radius: var(--fo-radius);
}

.fo-expiry[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Administration
   -------------------------------------------------------------------------- */

/* A segmented tab bar: one bordered strip, the current page filled. */
.fo-adminnav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  width: fit-content;
  max-width: 100%;
  margin-bottom: 20px;
  padding: 4px;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: calc(var(--fo-radius) + 4px);
  box-shadow: var(--fo-shadow-soft);
}

.fo-adminnav__link {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  min-height: var(--fo-touch);
  padding: 0 16px;
  color: var(--fo-muted);
  font-weight: 700;
  text-decoration: none;
  border-radius: var(--fo-radius);
  transition: background 120ms ease, color 120ms ease;
}

.fo-adminnav__link:hover { color: var(--fo-primary-dark); background: var(--fo-lavender); }

.fo-adminnav__link[aria-current="page"] { color: #fff; background: var(--fo-primary); }

.fo-table { margin: 0; --bs-table-bg: transparent; }
.fo-table th, .fo-table td { padding: 12px 10px; vertical-align: middle; border-color: var(--fo-line); }
.fo-table thead th { color: var(--fo-muted); font-size: 0.78rem; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; }
.fo-table tbody tr:last-child > * { border-bottom: 0; }
.fo-table__sub { color: var(--fo-muted); font-size: 0.875rem; }
.fo-table td.text-end form { display: inline-block; margin: 0; }

.fo-tag {
  display: inline-flex;
  gap: 4px;
  align-items: center;
  padding: 3px 10px;
  font-size: 0.78rem;
  font-weight: 700;
  white-space: nowrap;
  background: #eef0f7;
  border-radius: var(--fo-radius-pill);
}

.fo-tag--ok { color: #12684f; background: #dbf5ec; }
.fo-tag--off { color: #5c6178; background: #e9ebf3; }
.fo-tag--warn { color: #7a4a10; background: #fff1d6; }
.fo-tag--admin { color: #3f2fa5; background: #eeeafe; }

/* --------------------------------------------------------------------------
   The icon-and-PIN reply view.
   Deliberately plainer than a conversation: one card per person who wrote,
   what they said, and a box that answers them. Nothing to browse, nothing
   to get lost in, and never a doubt about who an answer goes to.
   -------------------------------------------------------------------------- */

.fo-quickview { display: grid; gap: 16px; margin: 4px 0 8px; }

.fo-chat {
  overflow: hidden;
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
  box-shadow: var(--fo-shadow-soft);
}

.fo-chat__heading {
  display: flex;
  gap: 10px;
  align-items: center;
  margin: 0;
  padding: 12px 16px;
  font-size: 1.05rem;
  font-weight: 800;
  border-bottom: 1px solid var(--fo-line);
}

.fo-chat__avatar {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  color: #fff;
  font-size: 0.95rem;
  font-weight: 800;
  text-transform: uppercase;
  background: linear-gradient(140deg, var(--fo-primary), var(--fo-secondary-deep));
  border-radius: 50%;
}

.fo-chat__list {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 14px 16px;
  list-style: none;
}

.fo-chat__msg {
  justify-self: start;
  max-width: 92%;
  padding: 8px 12px;
  background: var(--fo-sky);
  border: 1px solid #c4e0fc;
  border-radius: var(--fo-radius-lg);
  border-bottom-left-radius: 4px;
}

.fo-chat__body {
  margin: 0;
  font-size: 1.05rem;
  line-height: 1.45;
  white-space: pre-wrap;
  /* A message is text. Long words and pasted addresses wrap rather than
     stretching the card off the side of a phone. */
  overflow-wrap: anywhere;
}

.fo-chat__time { display: block; margin-top: 2px; color: var(--fo-muted); font-size: 0.75rem; }

.fo-chat__reply {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: flex-end;
  padding: 12px 16px 16px;
  background: var(--fo-canvas);
  border-top: 1px solid var(--fo-line);
}

.fo-chat__field { flex: 1 1 220px; width: auto; resize: vertical; }
.fo-chat__reply > .fo-button { flex: 0 0 auto; }

.fo-quickview__note { margin: 0; color: var(--fo-muted); font-size: 0.85rem; text-align: center; }

.fo-quickview__empty {
  margin: 0;
  padding: 28px 20px;
  text-align: center;
  color: var(--fo-muted);
  background: var(--fo-surface);
  border: 1px solid var(--fo-line);
  border-radius: var(--fo-radius-lg);
}

/* The "who has something waiting" banner on the homepage.
   Sits above the composer so it is read before anything else, and uses the
   info tone rather than a colour nobody has been taught. */
.fo-waiting { margin: 0 0 1rem; }

.fo-waiting__chime {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid #bcdcfb;
  border-radius: var(--fo-radius);
  background: #fff;
  color: #23417c;
  font-size: .95rem;
  font-weight: 700;
  cursor: pointer;
}

.fo-waiting__chime:hover { background: var(--fo-sky); }

/* --------------------------------------------------------------------------
   Responsive
   -------------------------------------------------------------------------- */

@media (max-width: 720px) {
  /* The playful offsets are a desktop-only flourish. On a phone the whole
     composition collapses to one honest column. */
  .fo-bubbles__item,
  .fo-constellation__item {
    transform: none;
  }

  .fo-msg { max-width: 92%; }
  .fo-panel { padding: 20px; }
  .fo-panel--wide { padding: 16px; }
  .fo-orbit--wide { display: none; }
  .fo-identity { width: 58px; height: 58px; font-size: 1.45rem; }
  .fo-adminnav { width: 100%; }
  .fo-adminnav__link { flex: 1 1 auto; justify-content: center; padding: 0 12px; }
}

@media (max-width: 560px) {
  /* The header buttons keep their words for a screen reader but show only
     their icons, so the name, the session and both buttons fit on one row. */
  .fo-headbtn { padding: 0; }

  .fo-headbtn__text,
  .fo-session__scope {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }

  .fo-session__who > .bi { display: none; }
  .fo-mark__sub { display: none; }

  .fo-composer { grid-template-columns: 1fr; }
  .fo-composer__send { grid-column: 1; grid-row: auto; }
  .fo-composer__count { grid-row: auto; }
  .fo-actions--row > .fo-button { flex: 1 1 auto; }
}

/* --------------------------------------------------------------------------
   Reduced motion. Everything decorative stops; nothing that conveys state or
   position depends on movement, so the interface stays complete without it.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .fo-send__button:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   Forced colours and high contrast
   -------------------------------------------------------------------------- */

@media (forced-colors: active) {
  .fo-sky { display: none; }

  .fo-identity,
  .fo-bubble {
    border: 2px solid ButtonText;
  }

  .fo-identity__input:checked + .fo-identity,
  .fo-bubble__input:checked + .fo-bubble {
    border-width: 4px;
  }
}
