/*
 * Framework-neutral Personal Hub visual primitives.
 *
 * The card idiom (.ph-card, .ph-card-footer, .ph-monogram) was retired on
 * 2026-08-23: project lists became .ph-line rows and the Mac's digest modules
 * became .ph-mod ruled sections, so nothing draws a rounded panel or a circular
 * monogram any more. Git history holds them if the decision is ever reversed.
 */

.ph-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}

.ph-status-dot {
  width: 7px;
  height: 7px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--status-online);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--status-online) 14%, transparent);
}

.ph-status-checking .ph-status-dot {
  background: var(--status-checking);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--status-checking) 14%, transparent);
}

.ph-status-offline .ph-status-dot {
  background: var(--status-offline);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--status-offline) 14%, transparent);
}

/*
 * Spine list — added 2026-08-23. The flat-ledger alternative to a card: full-width
 * rows carrying a colour spine instead of a box, chosen because it holds up at both
 * desktop and phone width where a fixed side column or an oversized title does not.
 *
 * Per-row colour comes from --line-accent. The mask uses --bg, never --panel: panel
 * is the lighter raised-surface token, so masking with it produces a card slab and
 * defeats the point. Lift comes from --lift instead — diffuse and radius-free, so
 * the block sits above the page without acquiring a panel edge.
 *
 * The masked surface belongs to the list, not the row: rows are contiguous inside a
 * list and their spines read as one rail, broken only where the accent changes.
 */

.ph-lines {
  display: flex;
  flex-direction: column;
  background: color-mix(in srgb, var(--bg) var(--mask), transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: var(--lift);
}

.ph-line {
  display: grid;
  color: inherit;
  text-decoration: none;
  grid-template-columns: 38px 1fr 1.05fr 128px;
  gap: 24px;
  align-items: baseline;
  padding: 20px 22px 18px;
  border-left: 3px solid var(--line-accent, var(--primary));
  border-bottom: 1px solid var(--hair);
  transition: background 180ms ease;
}

.ph-line:last-child {
  border-bottom: 0;
}

.ph-line:hover {
  background: var(--panel);
}

.ph-line-index {
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.ph-line-title {
  font-family: var(--font-editorial), Georgia, serif;
  font-size: 26px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.01em;
  transition: color 150ms ease;
}

.ph-line:hover .ph-line-title {
  color: var(--line-accent, var(--primary));
}

.ph-line-meta {
  margin-top: 6px;
  font-size: 12.5px;
  color: var(--muted);
}

.ph-line-blurb {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: pretty;
}

.ph-line-end {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 9px;
}

/*
 * An accent dot is tinted by its context, not by health: it labels what kind of
 * thing the line is ("Read-only", "Tailnet only", "Vault source"). Where the dot
 * reports a live check instead, use the .ph-status-* classes so the semantic
 * colour wins. Used by both .ph-line rows and .ph-mod footers.
 */
.ph-accent-dot {
  background: var(--line-accent, var(--primary));
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--line-accent, var(--primary)) 14%, transparent);
}

.ph-line-action {
  font-size: 13.5px;
  color: var(--muted);
  white-space: nowrap;
  transition: color 150ms ease;
}

.ph-line:hover .ph-line-action {
  color: var(--line-accent, var(--primary));
}

@media (max-width: 620px) {
  .ph-line {
    grid-template-columns: 1fr;
    gap: 10px;
    align-items: start;
    padding: 16px 12px 15px 12px;
  }

  .ph-line-title {
    font-size: 24px;
  }

  .ph-line-end {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    width: 100%;
  }
}


/*
 * A module is a block in the same ledger as a row list: same spine, same left edge,
 * same masked and lifted surface. Consecutive modules are separated by a real gap
 * rather than a shared rule, so the rail breaks between them and each block reads as
 * its own object — a continuous rail down the whole page made the sections run
 * together no matter how their content was spaced.
 */

.ph-mod {
  padding: 26px 22px 22px;
  border-left: 3px solid var(--line-accent, var(--primary));
  background: color-mix(in srgb, var(--bg) var(--mask), transparent);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: var(--lift);
}

/*
 * Centred, not baseline-aligned. Baseline pins the meta to the kicker — the small
 * line — so a bordered control beside it sits high against the title and reads as
 * misaligned. Centring balances the control group against the whole kicker+title block.
 */
.ph-mod-head {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 20px;
  align-items: center;
}

.ph-mod-kicker {
  margin-bottom: 5px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.ph-mod-title {
  margin: 0;
  font-family: var(--font-editorial), Georgia, serif;
  font-size: 27px;
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.012em;
}

.ph-mod-meta {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 12.5px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.ph-mod-sub {
  margin: 18px 0 8px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--muted);
}

.ph-mod-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
}

@media (max-width: 620px) {
  /* Horizontal padding is measure, and on a phone measure is the scarce thing: every
     px of inset here costs a wrapped line and therefore scroll. Vertical padding is
     kept; only the sides come in. */
  .ph-mod {
    padding: 20px 12px 18px;
  }

  /* The head stays two columns on a phone. Dropping the meta below the title cost a
     whole row of height per module and broke the alignment the desktop layout has;
     the meta is short enough to sit beside the title if it is allowed to wrap. */
  .ph-mod-head {
    gap: 12px;
  }

  .ph-mod-meta {
    gap: 8px;
    font-size: 11.5px;
    text-align: right;
  }

  .ph-mod-title {
    font-size: 25px;
  }
}

.ph-focus-ring:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 3px;
}

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

  .ph-line,
  .ph-line-title,
  .ph-line-action {
    transition: none;
  }
}
