/*
 * The opening components: the pieces a screen and a website both already
 * paint, and nothing else. A piece arrives here when it has a second user
 * and is shaped by both; until then it lives where it is needed.
 *
 * Every rule reads a token and mints no value of its own. Element defaults
 * are written with :where() so a consumer overrides them without a fight;
 * a class is used where there is no element to key on, or where a variant
 * has to be named.
 *
 * Each piece is complete before any script runs. Nothing here waits on
 * JavaScript to become visible, sized or readable.
 */

@layer nv.components {
  /* Layout ------------------------------------------------------------- */

  .nv-stack {
    display: flex;
    flex-direction: column;
    gap: var(--nv-stack-gap);
  }

  .nv-row {
    display: flex;
    flex-wrap: wrap;
    gap: var(--nv-space-2) var(--nv-space-4);
    align-items: baseline;
  }

  .nv-row[data-align='center'] {
    align-items: center;
  }

  /* The room a page has, named, so anything inside it can ask for it. It sets
     nothing else: it exists to be a container and wraps the page.

     Two questions, and neither of them is the window's. A component that
     reflows on its own width declares `container-type: inline-size` on itself
     and queries that; one that reflows on the page's asks `@container nv-page`.
     A width media query is illegal everywhere, because the same component in a
     sidebar and in a page answers one identically and is wrong in one of them.

     A container is a containing block for its fixed descendants, which is why
     an overlay belongs in the top layer, <dialog> or popover, where the kit
     already puts it. A hand-rolled position: fixed inside a page would be
     fixed to the page instead of the window, and that is the rule speaking. */
  .nv-viewport {
    container: nv-page / inline-size;
  }

  .nv-page {
    width: 100%;
    max-width: var(--nv-page-w-md);
    margin-inline: auto;
    padding-inline: var(--nv-page-gutter);
  }

  .nv-page[data-width='sm'] {
    max-width: var(--nv-page-w-sm);
  }

  .nv-page[data-width='lg'] {
    max-width: var(--nv-page-w-lg);
  }

  .nv-section {
    padding-block: var(--nv-section-gap);
  }

  /* Text roles ---------------------------------------------------------- */

  .nv-t-title {
    color: var(--nv-color-fg);
    font-family: var(--nv-font-display);
    font-size: var(--nv-text-3xl);
    font-weight: var(--nv-weight-semi);
    line-height: var(--nv-leading-tight);
    letter-spacing: -0.02em;
  }

  .nv-t-lead {
    color: var(--nv-color-fg);
    font-size: var(--nv-text-xl);
    line-height: var(--nv-leading-normal);
  }

  .nv-t-body {
    color: var(--nv-color-fg-body);
    font-size: var(--nv-text-base);
  }

  .nv-t-quiet {
    color: var(--nv-color-fg-muted);
    font-size: var(--nv-text-sm);
  }

  .nv-t-label {
    color: var(--nv-color-fg-muted);
    font-size: var(--nv-text-xs);
    font-weight: var(--nv-weight-medium);
    text-transform: uppercase;
    letter-spacing: 0.06em;
  }

  /* Controls ------------------------------------------------------------ */

  .nv-button {
    display: inline-flex;
    gap: var(--nv-space-2);
    align-items: center;
    justify-content: center;
    min-height: max(var(--nv-control-md), var(--nv-tap-target));
    padding-inline: var(--nv-space-4);
    font-size: var(--nv-text-sm);
    font-weight: var(--nv-weight-medium);
    color: var(--nv-color-fg-on-accent);
    text-decoration: none;
    cursor: pointer;
    background: var(--nv-color-accent);
    border: 1px solid transparent;
    border-radius: var(--nv-radius-md);
    transition: background var(--nv-duration-fast) var(--nv-ease-out);
  }

  .nv-button:hover {
    background: var(--nv-color-accent-hover);
  }

  .nv-button:active {
    background: var(--nv-color-accent-active);
  }

  .nv-button[disabled],
  .nv-button[aria-disabled='true'] {
    cursor: not-allowed;
    opacity: 0.55;
  }

  .nv-button[data-variant='quiet'] {
    color: var(--nv-color-fg);
    background: transparent;
    border-color: var(--nv-color-border-strong);
  }

  .nv-button[data-variant='quiet']:hover {
    background: var(--nv-color-bg-raised-hover);
  }

  .nv-button[data-variant='bare'] {
    min-height: max(var(--nv-control-sm), var(--nv-tap-target));
    padding-inline: var(--nv-space-2);
    color: var(--nv-color-fg-muted);
    background: transparent;
  }

  .nv-button[data-variant='bare']:hover {
    color: var(--nv-color-fg);
    background: var(--nv-color-bg-raised-hover);
  }

  .nv-button[data-variant='danger'] {
    color: var(--nv-color-fg-on-danger);
    background: var(--nv-color-danger);
  }

  .nv-button[data-variant='danger']:hover {
    background: var(--nv-color-danger-hover);
  }

  /* Fields -------------------------------------------------------------- */

  :where(input:not([type='checkbox'], [type='radio']), select, textarea) {
    width: 100%;
    min-height: max(var(--nv-control-md), var(--nv-tap-target));
    padding: var(--nv-space-2) var(--nv-space-3);
    font-size: var(--nv-text-input);
    color: var(--nv-color-fg);
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border-strong);
    border-radius: var(--nv-radius-md);
  }

  :where(textarea) {
    min-height: calc(var(--nv-control-md) * 2);
    resize: vertical;
  }

  :where(input, select, textarea):disabled {
    cursor: not-allowed;
    opacity: 0.55;
  }

  :where(input, select, textarea)[aria-invalid='true'] {
    border-color: var(--nv-color-danger);
  }

  :where(input[type='checkbox'], input[type='radio']) {
    width: var(--nv-icon-md);
    height: var(--nv-icon-md);
    accent-color: var(--nv-color-accent);
  }

  .nv-field {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-1);
  }

  .nv-field > label {
    color: var(--nv-color-fg);
    font-size: var(--nv-text-sm);
    font-weight: var(--nv-weight-medium);
  }

  .nv-field > .nv-hint {
    color: var(--nv-color-fg-muted);
    font-size: var(--nv-text-xs);
  }

  .nv-field > .nv-error {
    color: var(--nv-color-danger);
    font-size: var(--nv-text-xs);
  }

  .nv-field[data-inline] {
    flex-direction: row;
    gap: var(--nv-space-2);
    align-items: center;
  }

  :where(fieldset) {
    display: flex;
    flex-direction: column;
    gap: var(--nv-form-gap);
    padding: var(--nv-card-pad);
    margin: 0;
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-md);
  }

  :where(legend) {
    padding-inline: var(--nv-space-2);
    color: var(--nv-color-fg);
    font-size: var(--nv-text-sm);
    font-weight: var(--nv-weight-medium);
  }

  /* Surfaces ------------------------------------------------------------ */

  .nv-card {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-2);
    padding: var(--nv-card-pad);
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-lg);
  }

  .nv-cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
    gap: var(--nv-space-4);
  }

  .nv-notice {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-1);
    padding: var(--nv-space-3) var(--nv-space-4);
    color: var(--nv-color-fg);
    background: var(--nv-color-info-subtle);
    border-inline-start: 3px solid var(--nv-color-info);
    border-radius: var(--nv-radius-sm);
  }

  .nv-notice[data-tone='success'] {
    background: var(--nv-color-success-subtle);
    border-inline-start-color: var(--nv-color-success);
  }

  .nv-notice[data-tone='warning'] {
    background: var(--nv-color-warning-subtle);
    border-inline-start-color: var(--nv-color-warning);
  }

  .nv-notice[data-tone='danger'] {
    background: var(--nv-color-danger-subtle);
    border-inline-start-color: var(--nv-color-danger);
  }

  /* A table is wide by nature. It scrolls inside its own box, because a
     page that scrolls sideways is a page nobody can read on a phone. */
  .nv-table-scroll {
    overflow-x: auto;
  }

  :where(table) {
    width: 100%;
    border-collapse: collapse;
  }

  :where(th, td) {
    padding: var(--nv-space-2) var(--nv-space-3);
    text-align: start;
    border-bottom: 1px solid var(--nv-color-border);
  }

  :where(th) {
    color: var(--nv-color-fg);
    font-size: var(--nv-text-sm);
    font-weight: var(--nv-weight-semi);
  }

  /* Shell ---------------------------------------------------------------- */

  /* The strip: what a screen switches between, worlds or relations, as a
     line of chips that stays at the top and scrolls sideways rather than
     wrapping, since a row that wrapped would push the page down by one line
     per world. It bleeds to the page's edges by the gutter it sits in, and
     it is translucent over what scrolls under it. */
  .nv-strip {
    position: sticky;
    inset-block-start: 0;
    z-index: var(--nv-z-sticky);
    display: flex;
    gap: var(--nv-space-2);
    padding-block: var(--nv-space-2);
    padding-inline: var(--nv-page-gutter);
    margin-inline: calc(-1 * var(--nv-page-gutter));
    overflow-x: auto;
    scrollbar-width: none;
    background: color-mix(in oklab, var(--nv-color-bg) 82%, transparent);
    backdrop-filter: blur(16px);
    border-block-end: 1px solid var(--nv-color-border);
  }

  .nv-strip::-webkit-scrollbar {
    display: none;
  }

  .nv-strip > * {
    flex: none;
  }

  /* A chip: one named thing among several, a world in the strip, a
     relation, where a human stands. `aria-current` is the one that is on;
     `data-tone` colours its dot for a state. */
  .nv-chip {
    display: inline-flex;
    gap: var(--nv-space-2);
    align-items: center;
    min-height: max(var(--nv-control-sm), var(--nv-tap-target));
    padding-inline: var(--nv-space-3);
    font-size: var(--nv-text-sm);
    font-weight: var(--nv-weight-medium);
    color: var(--nv-color-fg-muted);
    text-decoration: none;
    cursor: pointer;
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-full);
  }

  .nv-chip::before {
    flex: none;
    width: var(--nv-space-2);
    height: var(--nv-space-2);
    content: '';
    background: var(--nv-color-border-strong);
    border-radius: var(--nv-radius-full);
  }

  .nv-chip:hover {
    color: var(--nv-color-fg);
    background: var(--nv-color-bg-raised-hover);
  }

  .nv-chip[aria-current] {
    color: var(--nv-color-fg);
    background: var(--nv-color-accent-subtle);
    border-color: transparent;
  }

  .nv-chip[aria-current]::before {
    background: var(--nv-color-accent);
  }

  .nv-chip[data-tone='success']::before {
    background: var(--nv-color-success);
  }

  .nv-chip[data-tone='warning']::before {
    background: var(--nv-color-warning);
  }

  .nv-chip[data-tone='danger']::before {
    background: var(--nv-color-danger);
  }

  /* The bar: a page's own line, its name and where the human stands,
     wrapping when the two do not fit on one line. */
  .nv-bar {
    display: flex;
    flex-wrap: wrap;
    gap: var(--nv-space-2) var(--nv-space-4);
    align-items: baseline;
    padding-block: var(--nv-space-5) var(--nv-space-2);
  }

  .nv-bar > h1 {
    flex: 1 1 auto;
  }

  /* Lists and people ---------------------------------------------------- */

  /* Rows on one surface, a line between each, and never a box per row:
     people, contacts, requests, anything that is several of one thing. */
  .nv-list {
    display: flex;
    flex-direction: column;
    padding: 0;
    margin: 0;
    overflow: hidden;
    list-style: none;
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-lg);
  }

  .nv-item {
    padding: var(--nv-space-3) var(--nv-space-4);
  }

  .nv-item + .nv-item {
    border-block-start: 1px solid var(--nv-color-border);
  }

  /* One person, or one thing with a face: the picture, and the words beside
     it, centred on each other and never wrapping under. */
  .nv-person {
    display: flex;
    gap: var(--nv-space-3);
    align-items: center;
    min-width: 0;
  }

  .nv-person > .nv-stack {
    gap: 0;
    min-width: 0;
  }

  .nv-avatar {
    display: grid;
    flex: none;
    place-items: center;
    width: var(--nv-control-lg);
    height: var(--nv-control-lg);
    overflow: hidden;
    font-family: var(--nv-font-display);
    font-weight: var(--nv-weight-semi);
    color: var(--nv-color-accent);
    background: var(--nv-color-accent-subtle);
    border-radius: var(--nv-radius-full);
  }

  .nv-avatar > img {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }

  .nv-picture {
    max-height: var(--nv-space-9);
    border-radius: var(--nv-radius-md);
  }

  /* Regions --------------------------------------------------------------- */

  /* One thing on a lot of air: a front, a door, a first screen. */
  .nv-hero {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-3);
    max-width: var(--nv-page-w-sm);
    padding-block: var(--nv-space-8) var(--nv-space-6);
  }

  /* What happened, in order, down a line. */
  .nv-feed {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-3);
    padding-inline-start: var(--nv-space-4);
    border-inline-start: 2px solid var(--nv-color-border);
  }

  /* A guest section on another's page: its own surface, its own look
     inside it. `data-whole` is the section that is the whole page. */
  .nv-standing {
    display: flex;
    flex-direction: column;
    gap: var(--nv-space-3);
    padding: var(--nv-space-4);
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-xl);
    box-shadow: var(--nv-shadow-sm);
  }

  .nv-standing[data-whole] {
    padding: 0;
    background: transparent;
    border: 0;
    box-shadow: none;
  }

  /* Words about what came back ---------------------------------------- */

  /* An answer, under the form that asked it or where a page put it. The
     tone says what kind of answer it is. */
  .nv-answer {
    padding: var(--nv-space-2) var(--nv-space-3);
    border-inline-start: 3px solid var(--nv-color-accent);
    border-radius: var(--nv-radius-sm);
  }

  .nv-answer[data-tone='warning'] {
    border-inline-start-color: var(--nv-color-warning);
  }

  .nv-answer[data-tone='danger'] {
    border-inline-start-color: var(--nv-color-danger);
  }

  /* A key, a pk, an address: something copied and never read aloud. */
  .nv-key {
    display: inline-block;
    padding: var(--nv-space-05) var(--nv-space-2);
    font-family: var(--nv-font-mono);
    font-size: var(--nv-text-xs);
    color: var(--nv-color-fg-muted);
    overflow-wrap: anywhere;
    background: var(--nv-color-bg-sunken);
    border-radius: var(--nv-radius-sm);
  }

  /* Nothing here yet, said as a place rather than as a blank. */
  .nv-empty {
    padding: var(--nv-space-5) var(--nv-space-4);
    font-size: var(--nv-text-sm);
    color: var(--nv-color-fg-muted);
    text-align: center;
    border: 1px dashed var(--nv-color-border-strong);
    border-radius: var(--nv-radius-lg);
  }

  /* The theme control. The element wires the buttons up; without it they
     are still here, still labelled, and still legible. */
  nv-theme {
    display: inline-flex;
    gap: var(--nv-space-05);
    padding: var(--nv-space-05);
    background: var(--nv-color-bg-raised);
    border: 1px solid var(--nv-color-border);
    border-radius: var(--nv-radius-full);
  }

  nv-theme button[aria-pressed='true'] {
    color: var(--nv-color-fg);
    background: var(--nv-color-bg-raised-strong);
  }
}
