/* The component rules the v2 boards draw with, and the ones the web app will draw with
   (SPEC-V2-15 FR-8). One stylesheet for both, so a board and the screen it was signed off as cannot
   quietly drift apart.

   Never knows: what page it is on. Classes only — no `*`, `html`, `body`, `a` or any other bare
   element selector — so linking it restyles nothing that does not carry one of its class names: not
   the landing page, not the Playground, not a board's own header. The board page itself (its header,
   specimen grids, phone frame, and the outward email, chat and calendar drawings) stays in
   `docs/design/v2-mockups/v2.css`, which imports this file first.

   Every foundation value arrives through a var() from generated/tokens.css, which build-tokens.mjs
   writes from tokens.json (DS-R11). A literal colour here fails check:design. */

.say {
  margin: 0;
  font-size: var(--t-callout);
  line-height: 1.4;
  text-wrap: pretty;
}

.say + .say {
  margin-top: 6px;
}

.meta {
  margin: 6px 0 0;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

.num {
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- DS-V02 certainty marks */

.cert {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--t-footnote);
  font-weight: 500;
  color: var(--label-2);
}

.cert svg {
  flex: none;
}

.cert--worked {
  font-weight: 400;
  font-style: italic;
}

.cert--confirmed {
  color: var(--done);
}

/* ---------------------------------------------------------------- DS-C06 buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: var(--touch);
  min-height: var(--touch);
  padding: 0 16px;
  border: 0;
  border-radius: var(--r-control);
  background: transparent;
  color: var(--tint);
  font: inherit;
  font-size: var(--t-callout);
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  text-decoration: none;
  transition: background-color var(--fast) var(--ease), transform var(--fast) var(--ease);
}

.btn:active {
  transform: scale(0.97);
}

.btn--filled {
  background: var(--tint);
  color: var(--on-tint);
}

.btn--grey {
  background: var(--fill-3);
  color: var(--label);
}

.btn--plain {
  padding: 0 10px;
}

.btn[disabled],
.btn[aria-disabled="true"] {
  background: var(--fill-4);
  color: var(--label-2);
  cursor: default;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 14px;
}

/* ---------------------------------------------------------------- DS-C07 notice */

.notice {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: var(--r-control);
  font-size: var(--t-subhead);
  line-height: 1.35;
  /* A notice can carry an address the person typed; a long one breaks rather than running out of
     the box (the app's sign-in notices, SPEC-V2-15 PR 8). */
  overflow-wrap: anywhere;
}

.notice svg {
  flex: none;
  margin-top: 1px;
}

.notice--in-flight {
  color: var(--label-2);
  background: var(--fill-4);
}

.notice--outcome {
  color: var(--done);
  background: var(--done-wash);
}

.notice--attention {
  color: var(--needs);
  background: var(--needs-wash);
}

/* ---------------------------------------------------------------- DS-C04 source */

.source {
  margin: 12px 0 0;
  padding: 13px 15px;
  border-radius: var(--r-control);
  background: var(--fill-4);
}

.source-quote {
  margin: 0;
  font-family: var(--serif);
  font-size: var(--t-callout);
  line-height: 1.5;
}

.source-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 2px 10px;
  margin-top: 8px;
  font-size: var(--t-caption);
  color: var(--label-2);
}

.source-meta a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  margin: -12px 0;
  font-weight: 600;
}

/* DS-C20: the household's unchanged passage is open before the public page. Long quotes and
   honest source labels wrap at phone widths; nothing is shortened or hidden behind a tap. */
.source--household .source-quote {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.source--household .source-meta {
  overflow-wrap: anywhere;
}

/* ---------------------------------------------------------------- DS-C20 published source

   A school's own public page, read by Togetha, drawn inside an answer to the person's own
   question. It is DS-C04's block plus a label line and a hairline in place of the grey fill, so a
   person can tell at a glance that it is the school speaking and not their own letter. The quote,
   the meta line and its 44px link are DS-C04's own. Always open, on all four surfaces (unlike
   DS-C04's sheet on phones). Signed off by the founder on 9 October 2026. */

.source--published {
  background: transparent;
  border: 1px solid var(--separator-opaque);
}

.source .pub-label {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 6px;
  font-size: var(--t-subhead);
  font-weight: 600;
  line-height: 1.3;
}

.pub-label svg {
  flex: none;
  color: var(--label-2);
}

/* The fixed line under a copy Togetha tried to refresh and could not. Neutral grey, not the
   attention colour: nothing has failed that the person has to fix. Written against `.source` so it
   holds inside a conversation bubble, whose own paragraph rule would otherwise remove the gap. */
.source--published .meta {
  margin: 6px 0 0;
}

/* The page address. Two things DS-C04's `.source-meta a` leaves out, both found by looking at the
   app in a real browser:

   1. Its colour. The boards get the link colour from a bare `a` rule in their own page stylesheet,
      which the app does not have, so the address took the browser's default blue (and its own
      visited purple). It is the action colour, as every other link is.
   2. A long address. DS-C04's link keeps a one-line link 44px tall with a -12px margin top and
      bottom, which only works while it stays on one line: wrapped, the margin pulls the next line
      (the "Fetched" day) up over the last line of the address. Here the link reserves only the 20px
      that margin left it, and the 44px target is a pseudo-element reaching past the text, so a
      wrapped address simply takes the room it needs. A short address looks exactly as before. */
.source--published .source-meta a {
  position: relative;
  min-height: calc(var(--touch) - 24px);
  margin: 0;
  color: var(--tint);
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
  overflow-wrap: anywhere;
}

.source--published .source-meta a::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  /* Reach to 44px tall when the text is shorter than that, and not at all when it is taller. */
  inset-block: min(0px, calc((100% - var(--touch)) / 2));
}

/* The arrival label: built by the intake route from the envelope, never by a reading. It sits on
   its own line under the Source's title so the fact never borrows the reading's authority. */
.arrival {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

.arrival svg {
  flex: none;
}

/* ---------------------------------------------------------------- DS-C17 options (new, draft) */

.opts {
  margin: 0;
  padding: 0;
  border: 0;
  min-width: 0;
}

.opts legend {
  padding: 0;
  margin-bottom: 4px;
  font-size: var(--t-callout);
  font-weight: 600;
  line-height: 1.35;
}

.opts-why {
  margin: 0 0 12px;
}

.opt-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--separator);
}

.opt {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: var(--touch);
  padding: 10px 2px;
  border-bottom: 1px solid var(--separator);
  cursor: pointer;
}

.opt input {
  position: absolute;
  opacity: 0;
  width: 1px;
  height: 1px;
}

.opt-mark {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: var(--r-capsule);
  border: 1.5px solid var(--label-3);
  color: var(--on-tint);
  transition: background-color var(--fast) var(--ease), border-color var(--fast) var(--ease);
}

.opt-mark svg {
  opacity: 0;
}

.opt input:checked ~ .opt-mark {
  background: var(--tint);
  border-color: var(--tint);
}

.opt input:checked ~ .opt-mark svg {
  opacity: 1;
}

.opt input:focus-visible ~ .opt-mark {
  outline: 2px solid var(--tint);
  outline-offset: 2px;
}

.opt-text {
  flex: 1;
  min-width: 0;
  font-size: var(--t-callout);
}

.opt-hint {
  flex: none;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

/* Something else is always last, and it is a route rather than a peer: no radio, a chevron. */
.opt--else {
  color: var(--tint);
  font-weight: 600;
}

.opt--else .opt-mark {
  border: 0;
  color: var(--tint);
}

.opt--else .opt-mark svg {
  opacity: 1;
}

.else-open {
  padding: 12px 0 2px;
  border-bottom: 1px solid var(--separator);
}

.else-open p {
  margin: 0 0 8px;
  font-size: var(--t-subhead);
  font-weight: 600;
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/* On: pressed, checked, or holding open what it discloses (a Thread's source chip, DS-L05). The
   fill is how somebody looking down an opened block can tell which chip it came from. */
.chip[aria-pressed="true"],
.chip[aria-checked="true"],
.chip[aria-expanded="true"] {
  background: var(--tint);
  border-color: var(--tint);
  color: var(--on-tint);
}

.chip {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  min-width: var(--touch);
  padding: 0 14px;
  border: 1px solid var(--tint-edge);
  border-radius: var(--r-capsule);
  background: transparent;
  color: var(--tint);
  font: inherit;
  font-size: var(--t-subhead);
  font-weight: 600;
}

.field {
  display: block;
  width: 100%;
  min-height: var(--touch);
  margin-top: 10px;
  padding: 10px 12px;
  border: 1px solid var(--separator-opaque);
  border-radius: var(--r-control);
  background: var(--bg-grouped);
  color: var(--label);
  font: inherit;
  font-size: var(--t-callout);
}

.field::placeholder {
  color: var(--label-2);
}

.field-label {
  display: block;
  margin-top: 12px;
  font-size: var(--t-footnote);
  font-weight: 600;
  color: var(--label-2);
}

/* ---------------------------------------------------------------- DS-C18 activity line (new, draft) */

.did {
  margin: 0;
}

.did-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 0 0 4px;
  font-size: var(--t-headline);
  font-weight: 600;
}

.did-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.did-line {
  display: grid;
  /* `minmax(0, 1fr)`, not `1fr`: a long unbroken word in the sentence wraps inside its column
     rather than pushing Undo out of the line. */
  grid-template-columns: 3.1rem minmax(0, 1fr) auto;
  gap: 2px 10px;
  align-items: start;
  padding: 9px 0;
  border-top: 1px solid var(--separator);
  /* A link to one act (the brief's Undo, SPEC-V2-04 FR-21) lands with the line clear of a sticky
     bar above it. */
  scroll-margin-block: 6rem;
}

.did-line:first-child {
  border-top: 0;
}

.did-when {
  padding-top: 12px;
  font-size: var(--t-footnote);
  color: var(--label-2);
  font-variant-numeric: tabular-nums;
}

.did-what {
  padding-top: 10px;
  font-size: var(--t-subhead);
  line-height: 1.4;
  text-wrap: pretty;
  overflow-wrap: anywhere;
}

/* The reason under the sentence. Its own size and colour, so it reads the same whether it holds a
   `.cert` mark (the boards) or the app's *Read:* / *Worked out:* label and the reading's words. */
.did-why {
  display: block;
  margin-top: 2px;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

.did-line .btn {
  margin-right: -10px;
}

.did-line--undone .did-what > span:first-child {
  color: var(--label-2);
  text-decoration: line-through;
  text-decoration-color: var(--label-3);
}

.did-follow {
  grid-column: 2 / -1;
  margin: 0;
  font-size: var(--t-subhead);
}

/* *Earlier (4)*. A link on a board, a button in the app (it shows the rest in place), so it sets
   everything a button would otherwise bring of its own. */
.did-more {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: var(--touch);
  padding: 0;
  border: 0;
  border-top: 1px solid var(--separator);
  background: none;
  color: var(--tint);
  font: inherit;
  font-size: var(--t-subhead);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}

.cant {
  display: block;
  margin-top: 2px;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

/* A few seconds between Send and sent — the hold (A3, assumed). The bar is drawn from the
   server's own deadline, so the client counts nothing it could get wrong. */
.hold {
  position: relative;
  height: 3px;
  margin-top: 10px;
  border-radius: var(--r-capsule);
  background: var(--fill-3);
  overflow: hidden;
}

.hold::after {
  content: "";
  position: absolute;
  inset: 0 40% 0 0;
  background: var(--label-2);
}

/* ---------------------------------------------------------------- DS-C03 card, DS-C01 row */

.card-title {
  margin: 0 0 4px;
  font-size: var(--t-headline);
  font-weight: 600;
  line-height: 1.3;
  text-wrap: balance;
}

.state {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--t-footnote);
  font-weight: 500;
  color: var(--label-2);
}

.state--needs {
  color: var(--needs);
}

.state--done {
  color: var(--done);
}

.needs-dot {
  width: 8px;
  height: 8px;
  border-radius: var(--r-capsule);
  background: var(--needs-fill);
}

.rows {
  margin: 0;
  padding: 0;
  list-style: none;
}

.row {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  min-height: var(--touch);
  padding: 11px 0;
  border-bottom: 1px solid var(--separator);
}

.row:last-child {
  border-bottom: 0;
}

.row-body {
  flex: 1;
  min-width: 0;
}

.row-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: var(--t-callout);
  font-weight: 600;
  line-height: 1.3;
}

.row-sub {
  margin-top: 2px;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

.group-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 18px 0 2px;
  font-size: var(--t-footnote);
  font-weight: 600;
  color: var(--label-2);
}

.group-head:first-child {
  margin-top: 0;
}

/* ---------------------------------------------------------------- DS-C19 page view (new, draft) */

.letter-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 20px;
}

@media (min-width: 1120px) {
  .letter-layout {
    grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
    align-items: start;
  }
}

.page {
  position: relative;
  padding: 28px 26px 34px;
  background: var(--bg-raised);
  border: 1px solid var(--separator-opaque);
  border-radius: var(--r-card);
  font-family: var(--serif);
  font-size: var(--t-subhead);
  line-height: 1.5;
  color: var(--label);
}

.page-no {
  position: absolute;
  top: 10px;
  right: 14px;
  font-family: var(--ui);
  font-size: var(--t-caption);
  color: var(--label-2);
}

.page h3 {
  margin: 0 0 10px;
  font-size: var(--t-headline);
}

.page p {
  margin: 0 0 10px;
}

.page table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-footnote);
}

.page th,
.page td {
  padding: 6px 6px;
  text-align: left;
  border-bottom: 1px solid var(--separator-opaque);
  vertical-align: top;
}

/* The element the claim was read from. An outline, not a highlighter: it must not hide what it
   marks. Ink rather than the action blue, because nothing inside it can be pressed (DS-F02), and
   thicker and rounder than any rule a letter prints, so it reads as Togetha's mark, not the page's. */
.hit {
  outline: 2.5px solid var(--label);
  outline-offset: 2px;
  border-radius: var(--r-control);
  background: var(--fill-3);
}

.page--photo {
  background: var(--bg-sunken);
  transform: rotate(-0.6deg);
}

.page-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
  font-size: var(--t-footnote);
  color: var(--label-2);
}

.composer {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 8px var(--gutter);
  border-top: 1px solid var(--separator);
  background: var(--material);
}

.composer .field {
  margin: 0;
  border-radius: var(--r-capsule);
}

.tabbar {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  height: calc(var(--tab-h) + 18px);
  padding-bottom: 18px;
  border-top: 1px solid var(--separator);
  background: var(--material);
}

.tab {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  font-size: var(--t-caption2);
  font-weight: 500;
  color: var(--label-2);
  text-decoration: none;
}

.tab[aria-current="page"] {
  color: var(--tint);
}

.tab-badge {
  position: absolute;
  margin: -18px 0 0 22px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: var(--r-capsule);
  background: var(--fill-badge);
  color: var(--on-fill);
  font-size: var(--t-caption2);
  font-weight: 600;
  line-height: 18px;
  text-align: center;
}

.tab-icon {
  position: relative;
  display: grid;
  place-items: center;
}

.opt--button {
  width: 100%;
  border-top: 0;
  border-left: 0;
  border-right: 0;
  background: none;
  font: inherit;
  text-align: left;
}

/* A sender's answers inside a row: plain buttons, pulled left so their words line up with the row's. */
.row-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0 4px;
  margin: 4px 0 0 -10px;
}

/* The foot of the grouped new-senders item: its one secondary button, under a hairline. */
.item-foot {
  margin-top: 4px;
  padding-top: 12px;
  border-top: 1px solid var(--separator);
}

.item-foot .btn-row {
  margin-top: 0;
}

/* ---------------------------------------------------------------- Your Togetha address (settings-address.html)

   The address is data a person reads aloud, types into a school's form or pastes into a mail rule.
   It is set in the UI face, like everything else (founder, 2 October 2026, #1118): it is made of
   whole words, so there are no look-alike characters for a fixed-width face to separate. */

.address {
  margin: 12px 0 0;
  padding: 12px 14px;
  border-radius: var(--r-control);
  background: var(--bg-sunken);
  color: var(--label);
  font-size: var(--t-body);
  line-height: 1.35;
  overflow-wrap: anywhere;
  -webkit-user-select: all;
  user-select: all;
}

.dlg {
  max-width: 44rem;
  margin: 0 auto;
  padding: 8px 20px 24px;
  border-radius: var(--r-sheet);
  background: var(--bg-grouped);
  box-shadow: var(--lift);
}

/* DS-P14 (signed off 31 October 2026): the overlay as a full-height sheet below 768px and a dialog,
   36rem wide, from 768px (DS-C08's "Sheet" on a phone, `<dialog>` on the web). Its parent places it:
   stretched to the window's height on a phone, centred from 768px. Long contents scroll inside it,
   so the confirming field and its button are never behind a second layer. */
.dlg--sheet {
  box-sizing: border-box;
  width: 100%;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  border-radius: 0;
}

@media (min-width: 768px) {
  .dlg--sheet {
    width: min(100%, 36rem);
    max-height: calc(100dvh - 4rem);
    border-radius: var(--r-sheet);
  }
}

.dlg-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: var(--touch);
  margin-bottom: 8px;
}

.dlg-head h2 {
  margin: 0;
  font-size: var(--t-title3);
  letter-spacing: -0.01em;
}

/* A settings row that opens a page of its own: the whole row is the target, the chevron says so. */
.row--go {
  align-items: center;
  color: var(--label);
  text-decoration: none;
}

.row-go {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  color: var(--label-2);
  font-size: var(--t-subhead);
}

.row-go svg {
  color: var(--label-3);
}

/* Read by a screen reader, not drawn: the polite "Copied" status. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* The one plain line under a settings heading that says what the setting is for. */
.lede-line {
  margin: 0;
  color: var(--label-2);
  font-size: var(--t-subhead);
  line-height: 1.4;
  text-wrap: pretty;
}


/* DS-F08: motion stops under reduced motion. v2.css stops it for a whole board with a `*` rule; this
   file cannot use one, so it names its own two transitions. */
@media (prefers-reduced-motion: reduce) {
  .btn,
  .opt-mark {
    transition: none;
  }
}
