/* ==========================================================================
   Triumph Design System v3 — screen components
   --------------------------------------------------------------------------
   v3 does NOT fork v2. It loads v2's tokens.css and pattern.css unchanged and
   adds the component layer for SCREENS a member or a guest actually uses:
   portals, account pages, member-facing web. Print and promo stay on v2.
   Data dashboards stay on design.greenvilletriumph.club.

   Link order, always:
     tokens.css  →  pattern.css  →  components.css

   The four rules this layer exists to enforce
   -------------------------------------------
   1. TWO GROUNDS. Navy and fog. Never a third tone as a section background.
      A panel is #fff on fog, or navy on navy. Nothing in between.
   2. ONE CONTINUOUS FIELD. The weave is one field running the length of the
      page, not a texture restarted per section. See .field below.
   3. NO BOX IN A BOX IN A BOX. A filled panel may hold text and controls. It
      may not hold another filled panel that holds another filled panel.
      Dividing rules, not nested cards.
   4. COLOUR LIVES IN MARKS, NOT IN TYPE. Triumph Green and Lime never set
      type on a light surface; they fail contrast. Status colour goes in a
      swatch, a bar, or a mark, and the words stay navy.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. THE CONTINUOUS FIELD
   Every element that paints the weave starts its tile at its own top edge, so
   a page of stacked sections resets the pattern at every boundary and the
   tiles never meet. --field-y shifts each layer by that section's distance
   down the document, so the whole page reads as one field and only the ink
   changes at a seam.

   Pair with the alignField() helper in field.js. Without the JS this degrades
   to the old per-section behaviour; nothing breaks.
   -------------------------------------------------------------------------- */
.field { position: relative; isolation: isolate; overflow: hidden; }
.field > * { position: relative; z-index: 1; }
.field::before {
  content: ""; position: absolute; inset: 0;
  background: var(--brand-pattern-ink);
  -webkit-mask: var(--brand-weave) repeat; mask: var(--brand-weave) repeat;
  -webkit-mask-size: var(--brand-pattern-size); mask-size: var(--brand-pattern-size);
  -webkit-mask-position: 0 var(--field-y, 0px); mask-position: 0 var(--field-y, 0px);
  opacity: var(--field-o, .05);
  pointer-events: none; z-index: 0;
}
/* The two grounds. There is no third. */
.field-navy { --brand-pattern-ink: #ffffff; --field-o: .05; background: var(--navy); color: #fff; }
.field-fog  { --brand-pattern-ink: var(--navy); --field-o: .05; background: var(--fog); }

/* Running text never sits on the pattern. Give any block of copy on a navy
   field this fill: on navy it is invisible as a shape, and all it does is
   stop the weave behind the words. */
.on-solid { background: var(--navy); }


/* --------------------------------------------------------------------------
   2. APP BAR
   Mark, the name of the section you are in, and the member's initials. On a
   phone that is the whole bar, because the tab bar is the navigation. The
   lime rule is load-bearing: the bar and a navy hero carry the same weave, so
   without it the band has no edge. It also bookends the footer rule.
   -------------------------------------------------------------------------- */
.appbar {
  position: sticky; top: 0; z-index: 60;
  background: var(--navy);
  border-bottom: 2px solid var(--lime);
  isolation: isolate; overflow: hidden;
  transition: transform .28s cubic-bezier(.19,.9,.22,1);
}
.appbar::before {
  content: ""; position: absolute; inset: 0; background: #fff;
  -webkit-mask: var(--brand-weave) repeat; mask: var(--brand-weave) repeat;
  -webkit-mask-size: var(--brand-pattern-size); mask-size: var(--brand-pattern-size);
  opacity: .05; pointer-events: none; z-index: 0;
}
/* env() top inset: installed to a home screen this runs under the status bar. */
.appbar-in {
  position: relative; z-index: 1;
  max-width: 1280px; margin: 0 auto;
  padding: calc(11px + env(safe-area-inset-top)) clamp(16px,4vw,40px) 11px;
  display: flex; align-items: center; gap: clamp(14px,2vw,26px);
}
.appbar-id { display: flex; align-items: center; gap: 11px; min-width: 0; }
.appbar-id img { height: 30px; width: auto; display: block; flex: none; }
.appbar-where {
  font-size: var(--text-xs, .9rem); font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.appbar-nav { display: flex; gap: clamp(14px,1.7vw,24px); margin-left: auto; align-items: center; }
.appbar-nav a {
  color: var(--ink-muted-navy); font-size: var(--text-xs, .9rem); font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
  text-decoration: none; transition: color .16s ease;
}
.appbar-nav a:hover, .appbar-nav a.on { color: #fff; }
.appbar-avatar {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-full);
  background: var(--lime); color: var(--navy);
  font-size: var(--text-xs, .9rem); font-weight: 900;
  display: grid; place-items: center; letter-spacing: .02em;
}
/* Scrolling down gives the bar's height back to the content. */
.appbar.is-away { transform: translateY(-100%); }


/* --------------------------------------------------------------------------
   3. DIVIDED GRID
   Cells share one hairline: the grid paints the rules with a 1px gap over a
   hairline ground, and the cells carry NO borders of their own. Two rules in
   the same place read as a smudge, and a bordered card inside a bordered grid
   is rule 3 broken.
   -------------------------------------------------------------------------- */
.grid-divided {
  display: grid; gap: 1px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}
.grid-divided > * { background: var(--fog); border: 0; }
/* On a navy field the rules are white-alpha and the cells are navy. */
.grid-divided.on-navy { background: rgba(255,255,255,.13); border-color: rgba(255,255,255,.13); }
.grid-divided.on-navy > * { background: var(--navy); }
.grid-divided.cols-3 { grid-template-columns: repeat(3,1fr); }
.grid-divided.cols-fit { grid-template-columns: repeat(auto-fit,minmax(250px,1fr)); }
@media (max-width: 720px) {
  .grid-divided.cols-3 { grid-template-columns: 1fr; }
}


/* --------------------------------------------------------------------------
   4. TILE
   Less is more: a heading and the ONE value someone came for, then Details.
   Every other fact belongs in the sheet. A tile is a <button>, so the whole
   surface is the target, not a 20px link at the bottom.
   -------------------------------------------------------------------------- */
.tile {
  width: 100%; text-align: left; font: inherit; color: inherit; cursor: pointer;
  padding: clamp(22px,2.7vw,34px); border: 0;
  display: flex; flex-direction: column;
  transition: background .16s ease;
}
.tile:hover, .tile:focus-visible { background: #fff; }
.grid-divided.on-navy .tile:hover,
.grid-divided.on-navy .tile:focus-visible { background: rgba(255,255,255,.055); outline: none; }
.tile-no {
  font-family: var(--font-display); font-weight: 400; font-size: 2.2rem; line-height: 1;
  color: color-mix(in srgb, var(--navy) 38%, transparent);
}
.grid-divided.on-navy .tile-no { color: var(--lime); }
.tile h3 { font-size: var(--text-lg, 1.25rem); font-weight: 900; color: var(--navy); margin: 12px 0 6px; letter-spacing: -.01em; }
.tile-lede { margin: 0 0 18px; font-size: var(--text-body, 1rem); font-weight: 700; line-height: 1.4; color: var(--ink-body); text-wrap: pretty; }
.tile-more {
  margin-top: auto; align-self: flex-start;
  font-size: var(--text-sm, .95rem); font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--navy);
  border-bottom: 3px solid var(--green); padding-bottom: 5px;
}
.tile:hover .tile-more { color: var(--green-dark); border-color: var(--lime); }
.grid-divided.on-navy .tile h3 { color: #fff; }
.grid-divided.on-navy .tile-lede { color: var(--ink-muted-navy); }
.grid-divided.on-navy .tile-more { color: #cfe0f0; border-bottom-color: var(--lime); }
.grid-divided.on-navy .tile:hover .tile-more { color: var(--lime); }


/* --------------------------------------------------------------------------
   5. LEDGER
   A long dated list on ONE surface. Month headings are divider rows inside the
   panel, not separate cards, so the whole history is a single box no matter
   how many rows it holds. Cap the column: date, subject, and outcome have to
   sit together, and a 1280px row leaves them oceans apart.
   -------------------------------------------------------------------------- */
.ledger { background: #fff; border: 1px solid var(--hairline); padding: 4px clamp(16px,2vw,24px) 16px; max-width: 640px; }
.ledger-month {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  padding: 22px 0 8px; border-bottom: 2px solid var(--navy);
}
.ledger-month b { font-size: var(--text-sm, .95rem); font-weight: 900; letter-spacing: .12em; text-transform: uppercase; color: var(--navy); }
.ledger-month span {
  font-family: var(--font-mono); font-size: var(--text-xs, .9rem); font-weight: 600;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-body); opacity: .62; white-space: nowrap;
}
.ledger-row {
  display: grid; grid-template-columns: 46px minmax(0,1fr) auto; gap: 14px; align-items: center;
  width: 100%; text-align: left; font: inherit; color: inherit;
  background: none; border: 0; border-bottom: 1px solid var(--hairline);
  padding: 13px 0; cursor: pointer; transition: background .16s ease;
}
.ledger-row:last-child, .ledger-row.is-last { border-bottom: 0; }
.ledger-row:hover, .ledger-row:focus-visible { background: var(--fog); }
.ledger-date { display: flex; flex-direction: column; align-items: flex-start; gap: 3px; padding-top: 1px; }
.ledger-date b { font-family: var(--font-mono); font-size: var(--text-xs, .9rem); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-body); opacity: .62; }
.ledger-date i { font-style: normal; font-variant-numeric: tabular-nums; font-size: 1.5rem; font-weight: 900; line-height: 1; letter-spacing: -.03em; color: var(--navy); }
.ledger-subject { display: block; font-size: var(--text-body, 1rem); font-weight: 800; line-height: 1.25; letter-spacing: -.01em; color: var(--navy); text-wrap: pretty; }
.ledger-sub { display: block; margin-top: 4px; font-size: var(--text-sm, .95rem); line-height: 1.45; color: var(--ink-body); opacity: .8; }
.ledger-out { justify-self: end; align-self: center; text-align: right; }
@media (max-width: 720px) {
  .ledger { padding-left: 14px; padding-right: 14px; }
}


/* --------------------------------------------------------------------------
   6. STATUS: WORD + MARKS + LEGEND
   Rule 4 in practice. The word stays navy so it passes contrast on white; the
   colour is carried by the mark under it and the legend swatch above the list.
   Settled states read at full weight, open ones recede.
   -------------------------------------------------------------------------- */
.status-word {
  display: block; font-family: var(--font-mono);
  font-size: var(--text-xs, .9rem); font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; white-space: nowrap; color: var(--navy);
}
.status-word.is-open { font-weight: 600; color: color-mix(in srgb, var(--navy) 50%, transparent); }

/* One mark per item, until that stops being readable. Past six, collapse to
   one mark per distinct outcome; see the scaling rule in SKILL.md. */
.status-marks { display: flex; flex-wrap: wrap; gap: 3px; justify-content: flex-end; margin-top: 6px; max-width: 132px; }
.status-marks i { width: 18px; height: 5px; display: block; }

.legend { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.legend span { display: flex; align-items: center; gap: 8px; font-size: var(--text-xs, .9rem); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-body); }
.legend i { width: 10px; height: 10px; flex: none; display: block; }

/* The four states. Use these on legend swatches and status marks only. */
.st-good    { background: var(--green); }
.st-moved   { background: var(--sky); }
.st-none    { background: color-mix(in srgb, var(--navy) 30%, transparent); }
.st-open    { background: color-mix(in srgb, var(--navy) 12%, transparent); }
.legend .st-open { background: none; border: 1.5px solid color-mix(in srgb, var(--navy) 38%, transparent); }


/* --------------------------------------------------------------------------
   7. DETAIL SHEET
   ONE sheet for the whole page. Tiles, ledger rows and cards all open it. That
   is what lets every surface show a headline and one value: the facts, the
   paragraph and the links are always one tap away, never inline.
   -------------------------------------------------------------------------- */
.sheet-scrim { position: fixed; inset: 0; z-index: 90; background: rgba(2,0,34,.72); display: none; align-items: center; justify-content: center; padding: 20px; overscroll-behavior: contain; }
.sheet-scrim.open { display: flex; }
.sheet { background: var(--fog); color: var(--ink-body); width: 100%; max-width: 470px; max-height: min(88dvh, 680px); overflow-y: auto; padding: clamp(26px,4vw,38px); position: relative; box-shadow: 0 40px 80px rgba(2,0,34,.5); }
.sheet::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 6px; background: var(--grad-hero); }
.sheet h3 { font-family: var(--font-display); font-weight: 400; font-size: 2rem; color: var(--navy); margin: 8px 0 6px; letter-spacing: .02em; }
.sheet-meta { font-family: var(--font-mono); font-size: var(--text-xs, .9rem); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--green-dark); margin-bottom: 12px; }
.sheet p { font-size: var(--text-sm, .95rem); line-height: 1.5; margin: 0 0 20px; }
.sheet-close { position: absolute; top: 8px; right: 8px; min-width: 44px; min-height: 44px; display: flex; align-items: center; justify-content: center; background: none; border: 0; font-size: 1.5rem; color: var(--navy); cursor: pointer; line-height: 1; }
.sheet-row { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
@media (max-width: 720px) {
  .sheet-scrim { align-items: flex-end; padding: 0; }
  .sheet { max-width: none; }
}

/* Label-and-value, the way facts belong in a sheet. Never a paragraph poured
   into a box. */
.facts { margin: 0 0 20px; display: grid; grid-template-columns: auto minmax(0,1fr); gap: 9px 16px; align-items: baseline; }
.facts dt { font-family: var(--font-mono); font-size: var(--text-xs, .9rem); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-body); opacity: .75; white-space: nowrap; }
.facts dd { margin: 0; font-size: var(--text-body, 1rem); font-weight: 800; color: var(--navy); line-height: 1.35; }
.facts dd.long { font-weight: 600; font-size: var(--text-sm, .95rem); line-height: 1.45; }
