/* The family's pages — sign-in, and (Task 9) the veteran's page.
 * A small sheet hanging off the tokens declared at the top of /styles.css;
 * nothing here is a magic value that isn't a token there. */

/* The page is a tinted ground; the content sits on cards above it. That
 * separation is what stops the whole thing reading as one flat document —
 * it's doing the work borders used to do, with space and surface instead. */
.portal { background: var(--paper-2); }

.portal-main {
  max-width: 46rem;
  margin-inline: auto;
  padding: var(--sp-4) var(--edge) var(--sp-5);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.portal-main--veteran {
  max-width: 68rem;
  padding-top: var(--sp-3);
}

.portal-veteran {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.portal-bar {
  min-height: 3.4rem;
  padding: 0 var(--sp-1) var(--sp-1);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  border-bottom: 1px solid var(--line);
}

.portal-bar__brand {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--ink);
  font-size: 0.8rem;
  font-weight: 750;
  letter-spacing: 0.07em;
  text-decoration: none;
  text-transform: uppercase;
}

.portal-bar__brand img {
  width: 2rem;
  height: 2rem;
  object-fit: contain;
}

.portal-bar .back {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.portal-main h1 { margin-bottom: var(--sp-2); }
.portal-main .lede { margin-bottom: var(--sp-3); }

/* A card. One per section, so the eye can tell what belongs to what. */
.panel {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: var(--sp-3);
}

.panel > h2 { margin: 0 0 var(--sp-2); font-size: var(--step-1); }
.panel__foot { margin: var(--sp-3) 0 0; font-size: 0.94rem; }

/* The name, the state, and the shorthand — three lines that used to be three
 * separate blocks with a bold sentence between them. */
.vet-head {
  padding: var(--sp-2) var(--sp-1) var(--sp-1);
  border-bottom: 1px solid var(--line);
}
.vet-head h1 {
  margin: 0;
  max-width: 18ch;
  font-size: clamp(2.25rem, 5vw, 4.2rem);
  letter-spacing: -0.025em;
}

.vet-head__state {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
}

.vet-head__meta {
  margin: 0.5rem 0 0;
  font-size: 0.94rem;
  color: var(--ink-soft);
  letter-spacing: 0.01em;
}

/* The two things a family comes back for share the first working surface:
 * where the project stands, and what we most recently sent them. */
.progress-board {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(16rem, 0.75fr);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background: var(--paper);
  overflow: hidden;
}

.progress-card,
.latest-card {
  min-width: 0;
  padding: clamp(1.25rem, 3vw, 2rem);
}

.latest-card {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--line);
  background: oklch(0.975 0.008 100);
}

.portal-kicker {
  margin: 0 0 0.7rem;
  color: oklch(0.39 0.055 128);
  font-size: 0.76rem;
  font-weight: 750;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.progress-card__number {
  display: flex;
  align-items: baseline;
  gap: 0.65rem;
}

.progress-card__number strong {
  color: oklch(0.34 0.055 128);
  font-family: var(--serif);
  font-size: clamp(3rem, 7vw, 5.1rem);
  font-weight: 500;
  line-height: 0.95;
  letter-spacing: -0.035em;
  font-variant-numeric: tabular-nums;
}

.progress-card__number span {
  color: var(--ink-soft);
  font-weight: 650;
}

.progress-track {
  height: 0.6rem;
  margin: 1.25rem 0;
  overflow: hidden;
  border-radius: 999px;
  background: var(--paper-3);
}

.progress-track > span {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: oklch(0.39 0.065 128);
}

.progress-card__stage {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.4rem 1rem;
}

.progress-card__stage span {
  color: var(--ink-soft);
  font-size: 0.88rem;
}

.progress-card__stage strong {
  color: oklch(0.34 0.055 128);
  font-size: var(--step-0);
}

.progress-card__note {
  max-width: 56ch;
  margin: 1.1rem 0 0;
  font-size: var(--step-0);
  line-height: 1.55;
}

.progress-card__updated,
.latest-card__date {
  margin: 0.8rem 0 0;
  color: var(--ink-soft);
  font-size: 0.86rem;
}

.latest-card__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.latest-card blockquote {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 2vw, 1.45rem);
  line-height: 1.45;
}

.latest-card__empty {
  margin: 0;
  color: var(--ink-soft);
}

.latest-card__link {
  min-height: 44px;
  margin-top: 1rem;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  color: oklch(0.39 0.055 128);
  font-weight: 700;
  text-decoration: none;
}

.latest-card__link:hover { text-decoration: underline; }

.latest-file {
  min-height: 56px;
  padding: 0.65rem;
  display: flex;
  align-items: center;
  gap: 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: inherit;
  text-decoration: none;
}

.latest-file span { min-width: 0; display: flex; flex-direction: column; }
.latest-file strong { overflow-wrap: anywhere; }
.latest-file small { color: var(--ink-soft); }

.know-panel { padding: 0; overflow: hidden; }
.know-panel summary {
  min-height: 5.5rem;
  padding: var(--sp-2) var(--sp-3);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  cursor: pointer;
  list-style: none;
}
.know-panel summary::-webkit-details-marker { display: none; }
.know-panel summary > span:first-child {
  display: flex;
  flex-direction: column;
}
.know-panel summary strong {
  font-family: var(--serif);
  font-size: var(--step-1);
  font-weight: 550;
}
.know-panel__action {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  color: oklch(0.39 0.055 128);
  font-weight: 700;
  white-space: nowrap;
}
.know-panel[open] .know-panel__action { font-size: 0; }
.know-panel[open] .know-panel__action::after { content: "Hide details"; font-size: 0.94rem; }
.know-panel__body {
  padding: var(--sp-3);
  border-top: 1px solid var(--line);
}

.pay-panel,
.story-panel { box-shadow: none; }

@media (max-width: 44rem) {
  .portal-main--veteran { padding-top: var(--sp-2); }
  .progress-board { grid-template-columns: 1fr; }
  .latest-card { border-left: 0; border-top: 1px solid var(--line); }
  .progress-card__stage { align-items: flex-start; flex-direction: column; }
  .know-panel summary { align-items: flex-start; flex-direction: column; }
  .portal-bar__brand span { max-width: 15ch; line-height: 1.25; }
}

/* The state at a glance. Carries its own text, never colour alone — the
 * sentence beside it is still what says what is happening. */
.chip-status {
  display: inline-flex;
  align-items: center;
  padding: 0.3em 0.85em;
  border-radius: 999px;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
  background: var(--paper-3);
  color: var(--ink);
  border: 1px solid var(--line-2);
}

.chip-status[data-status="active"] {
  background: oklch(0.735 0.115 74 / 0.16);
  border-color: oklch(0.735 0.115 74 / 0.45);
}

.chip-status[data-status="done"] {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.portal-form {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  max-width: 26rem;
}

.portal-form label {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
}

.portal-form input {
  font: inherit;
  font-size: 1rem; /* >=17px in practice once the fluid base scale is applied */
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  min-height: 44px;
}

.portal-form input:hover { border-color: var(--ink-soft); }
.portal-form input:focus {
  outline: none;
  border-color: var(--brass);
  box-shadow: 0 0 0 3px oklch(0.735 0.115 74 / 0.22);
}
.portal-form input:focus-visible {
  outline: 3px solid var(--brass);
  outline-offset: 2px;
}

.portal-form button {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: var(--step-0);
  min-height: 44px;
  padding: 0.85em 1.6em;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--brass);
  color: oklch(0.24 0.03 60);
  box-shadow: var(--shadow-1);
}
.portal-form button:hover { box-shadow: var(--shadow-2); }
.portal-form button:focus-visible {
  outline: 3px solid var(--brass);
  outline-offset: 2px;
}

/* A real sentence, not a colour swatch — role="alert" carries it to a screen
 * reader, and the wording itself (not the tint) is what tells a reader
 * something went wrong. */
.error {
  color: var(--danger);
  font-weight: 500;
}

.quiet {
  color: var(--ink-soft);
  font-size: 0.94rem;
  margin-top: var(--sp-4);
}

.back {
  color: var(--ink-soft);
  font-size: 0.94rem;
  text-decoration: underline;
}

/* The sentence a family came to read. Weight and size carry the meaning, not
 * colour alone — the wording itself ("We're looking...") is the signal. */
.status {
  font-size: var(--step-0);
  font-weight: 500;
  color: var(--ink);
}

/* A grid, not fourteen ruled rows. The gaps do the separating, which is both
 * quieter and about 60% shorter — the conversation below is what the family
 * actually came for, and it should not sit two screens down. */
.facts {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--sp-2) var(--sp-3);
}

.fact { min-width: 0; }

/* A paragraph a family typed does not belong in a column beside "Army". */
.fact--wide { grid-column: 1 / -1; }

/* Uppercase and tracked reads as a label rather than a sentence, so the value
 * below it carries the weight. Not smaller than this: the audience skews older
 * and these are the words that say what they're looking at. */
.fact dt {
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.fact dd {
  margin: 0.25em 0 0;
  font-size: var(--step-0);
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.requests {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

/* Each veteran is a card, same surface language as their own page. */
.requests li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-1) var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
}

.requests a {
  font-size: var(--step-1);
  font-weight: 600;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  margin-right: auto;
}

.requests .status {
  flex-basis: 100%;
  font-size: 0.94rem;
  color: var(--ink-soft);
}

.signout { margin-top: var(--sp-4); }

/* A real <button> inside a real <form method="post">, styled to read as a
 * plain link — sign-out must be a POST, not a GET a link prefetch could fire. */
.link-button {
  font: inherit;
  font-size: 0.94rem;
  color: var(--ink-soft);
  background: none;
  border: none;
  padding: 0;
  min-height: 44px;
  text-decoration: underline;
  cursor: pointer;
}

.link-button:hover { color: var(--ink); }
.link-button:focus-visible {
  outline: 3px solid var(--brass);
  outline-offset: 2px;
}

/* A conversation between two people, in the site's own palette rather than a
 * chat app's. Who spoke is carried three ways at once — avatar, byline, and
 * which side the bubble sits on — so colour is never doing the work alone. */
.chat {
  list-style: none;
  margin: var(--sp-3) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
}

.entry {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-1);
  max-width: 85%;
}

/* Space between speakers, not between every line one person said. */
.entry.run-start { margin-top: var(--sp-2); }

.entry.mine {
  align-self: flex-end;
  flex-direction: row-reverse;
}

.avatar {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 0.95rem;
  background: var(--brass);
  color: oklch(0.24 0.03 60);
}

.avatar--ty { background: var(--ink); color: var(--paper); }

/* Holds the indent for a follow-on bubble without repeating the face. */
.avatar--spacer { background: none; height: 0; }

.entry__stack { min-width: 0; display: flex; flex-direction: column; }
.entry.mine .entry__stack { align-items: flex-end; }

.byline {
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--ink-soft);
  margin-bottom: 0.25em;
}

.byline .quiet { margin-top: 0; font-size: inherit; font-weight: 500; }

.bubble {
  background: var(--bubble-theirs);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0.7rem 0.95rem;
  max-width: 100%;
}

.entry.mine .bubble {
  background: var(--bubble-mine);
  border-color: var(--line-2);
}

.said {
  font-size: var(--step-0);
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* A file that looks like a file. The whole card is the download link — a
 * target well past 44px, not a bare filename to hit. */
.doc-card {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  min-height: 44px;
  text-decoration: none;
  color: var(--ink);
}

.doc-card__icon { flex: none; color: var(--ink-soft); }
.doc-card__icon--pdf { color: var(--danger); }

.doc-card__text { display: flex; flex-direction: column; min-width: 0; }

.doc-card__name {
  font-weight: 600;
  text-decoration: underline;
  overflow-wrap: anywhere;
}

.doc-card__size { font-size: 0.9rem; color: var(--ink-soft); }
.doc-card__note { font-size: 0.9rem; color: var(--ink-soft); }
.doc-card__note::before { content: " · "; }

/* A photo shows itself. Capped so a phone scan doesn't fill the screen;
 * the filename underneath is still the plain download. */
.thumb { display: block; }

.thumb img {
  display: block;
  max-width: 100%;
  max-height: 260px;
  border-radius: 10px;
}

.thumb__meta {
  font-size: 0.9rem;
  margin: 0.35em 0 0;
}

.thumb__meta a { color: var(--ink-soft); }

.inline { display: inline; }

.say {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  max-width: 34rem;
}

.say label {
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--ink);
}

.say textarea {
  font: inherit;
  font-size: 1rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
  padding: 0.85rem 1rem;
  resize: vertical;
}

.say textarea:focus,
.say input[type="file"]:focus-visible {
  outline: none;
  border-color: var(--brass);
  box-shadow: 0 0 0 3px oklch(0.735 0.115 74 / 0.22);
}

.say input[type="file"] {
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  min-height: 44px;
}

.help {
  font-size: 0.9rem;
  color: var(--ink-soft);
  margin: 0;
}

/* :not(.link-button) — the dropzone's "choose them" is a <button> living inside
 * this form, and without the exclusion it wore the Send button's brass pill,
 * which read as the primary action mid-sentence. */
.say button:not(.link-button) {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  font-size: var(--step-0);
  min-height: 44px;
  padding: 0.85em 1.6em;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--brass);
  color: oklch(0.24 0.03 60);
  box-shadow: var(--shadow-1);
}

.say button:not(.link-button):hover { box-shadow: var(--shadow-2); }
.say button:not(.link-button):focus-visible {
  outline: 3px solid var(--brass);
  outline-offset: 2px;
}

/* Inside a sentence, so it must not carry a 44px block height — the sentence
 * itself is the target's context and the text is the affordance. */
.dropzone-say .link-button {
  min-height: 0;
  font-size: inherit;
  font-weight: 600;
  color: var(--ink);
}

/* The dropzone sits in front of the real <input type="file">, which is only
 * ever hidden by the script that renders this element — see .visually-hidden.
 * Big on purpose: this is where a shoebox of scans arrives, so it should read
 * like Drive's "drop files here", not like a form control. The sentence, not
 * the glyph, is what tells someone who has never dragged a file what to do. */
.dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  text-align: center;
  border: 2px dashed var(--line-2);
  border-radius: var(--radius-sm);
  padding: var(--sp-4) var(--sp-3);
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.dropzone-glyph { color: var(--ink-soft); }

/* Armed: a file is in flight somewhere over the page. Over: it is above this
 * box. Both are carried by border weight and fill as well as colour — someone
 * relying on colour alone (or a monitor rendering it greyscale) still gets
 * the signal that the drop will land here. */
.dropzone.armed,
.dropzone.over {
  border-color: var(--brass);
  border-style: solid;
  background: oklch(0.735 0.115 74 / 0.08);
}

.dropzone.over { border-width: 3px; }

@media (prefers-reduced-motion: reduce) {
  .dropzone { transition: none; }
}

.dropzone-say {
  font-size: var(--step-0);
  color: var(--ink);
  margin: 0;
}

.dropzone-list {
  list-style: none;
  margin: var(--sp-1) 0 0;
  padding: 0;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.35em;
}

/* A picked file, waiting to go: a small card carrying its own remove. */
.pending {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  text-align: left;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--paper);
  font-size: 0.95rem;
}

.pending-name { font-weight: 600; overflow-wrap: anywhere; }
.pending-size { color: var(--ink-soft); white-space: nowrap; }

.pending-rm {
  margin-left: auto;
  flex: none;
  width: 44px;
  height: 44px;
  font: inherit;
  font-size: 1.3rem;
  line-height: 1;
  color: var(--ink-soft);
  background: none;
  border: none;
  border-radius: 50%;
  cursor: pointer;
}

.pending-rm:hover { color: var(--ink); background: var(--bubble-theirs); }
.pending-rm:focus-visible { outline: 3px solid var(--brass); outline-offset: 2px; }

/* Clipped, not display:none — the input stays focusable and stays part of
 * the form. Only the script ever adds this class, so with JS off the plain
 * <input type="file"> is exactly what's on the page. */
.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;
}

/* The payment ask. Warm card, not an invoice — see the note in views.js. */
.pay-panel {
  padding: var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow-1);
}

.pay-panel h2 { margin: 0 0 var(--sp-2); }
.pay-panel p { margin: 0 0 var(--sp-2); }
.pay-panel p:last-child { margin-bottom: 0; }

.pay {
  display: inline-block;
  font-weight: 600;
  min-height: 44px;          /* touch target floor — the audience skews older */
  padding: 0.85rem 1.4rem;
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: var(--paper);
  text-decoration: none;
}

.pay:hover { background: var(--ink-soft); }
.pay:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

.paid {
  margin-top: var(--sp-4);
  font-weight: 600;
}

/* The finished page. The warmest card on the page — this is the moment the
 * whole service exists for, so it reads as an arrival, not a receipt. */
.story-panel {
  padding: var(--sp-3);
  border: 1px solid oklch(0.735 0.115 74 / 0.55);
  border-radius: var(--radius);
  background: linear-gradient(
    oklch(0.735 0.115 74 / 0.10),
    oklch(0.735 0.115 74 / 0.04)
  ), var(--paper);
  box-shadow: var(--shadow-1);
}

.story-panel h2 { margin: 0 0 var(--sp-1); }
.story-panel p { margin: 0 0 var(--sp-2); }
.story-panel p:last-child { margin-bottom: 0; }

.story {
  display: inline-block;
  font-weight: 600;
  min-height: 44px;          /* touch target floor — the audience skews older */
  padding: 0.85rem 1.4rem;
  border-radius: var(--radius-sm);
  background: var(--brass);
  color: oklch(0.24 0.03 60);
  text-decoration: none;
}

.story:hover { box-shadow: var(--shadow-2); }
.story:focus-visible { outline: 3px solid var(--brass); outline-offset: 2px; }
