/* musketier-ui: base and components. Needs tokens.css linked before it.
   Mono carries the chrome (brand, nav, labels, meta, buttons, fields), Public
   Sans the body copy. Everything sits in layers, so an app's own unlayered
   rules always win, whatever their specificity. Element defaults of an app's
   own go into musketier-ui.base, where the components still outrank them. */

@layer musketier-ui.base {
  /* --- base --------------------------------------------------------------- */

  * { box-sizing: border-box; }

  body {
    margin: 0;
    background-color: var(--bg);
    color: var(--fg);
    font: 15px/1.55 var(--sans);
    -webkit-font-smoothing: antialiased;
  }

  /* One visible ring everywhere, since every page is keyboard-reachable. */
  :focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: var(--r-sm);
  }

  a {
    color: var(--accent);
    text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent);
    text-underline-offset: 0.2em;
  }
  a:hover { color: var(--fg); text-decoration-color: currentColor; }

  /* A string without spaces wraps rather than widening the page. */
  main {
    max-width: 62rem;
    margin: 0 auto;
    padding: 1.75rem 1.25rem 4rem;
    overflow-wrap: break-word;
  }

  h1 {
    font-family: var(--mono);
    font-size: 1.3rem;
    font-weight: 700;
    letter-spacing: -0.01em;
  }

  code { font-family: var(--mono); font-size: 0.86em; }

  label {
    display: block;
    margin-bottom: 0.3rem;
    font-family: var(--mono);
    font-size: var(--fs-ui);
    font-weight: 700;
  }
  /* A label that wraps its field rather than naming it with `for`. */
  label:has(> :is(input, select, textarea)) { display: grid; gap: 0.3rem; margin-bottom: 0; }

  :where(input:not([type="checkbox"], [type="radio"]), select, textarea) {
    width: 100%;
    min-height: 2.25rem;
    padding: 0.4rem 0.5rem;
    border: var(--rule) solid var(--line-strong);
    border-radius: var(--r);
    background: var(--bg-deep);
    color: var(--fg);
    font: inherit;
    font-family: var(--mono);
    font-size: var(--fs-ui);
    font-weight: 400;
    line-height: 1.5;
  }
  :where(input:not([type="checkbox"], [type="radio"]), select, textarea):hover { border-color: var(--muted); }
  :where(input, select, textarea):disabled { color: var(--muted); }
  ::placeholder { color: var(--muted); opacity: 0.7; }
  :where(textarea) { resize: vertical; }
  :where(input[type="checkbox"], input[type="radio"]) {
    flex: none;
    width: 0.95rem;
    height: 0.95rem;
    accent-color: var(--accent);
  }

  /* Only groups controls, e.g. so htmx can disable them together. */
  fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }

  @media (max-width: 40rem) {
    main { padding: 1rem 1rem 3rem; }
  }
}

@layer musketier-ui.components {
  /* --- text -------------------------------------------------------------- */

  .muted { color: var(--muted); }
  .meta { color: var(--muted); font-family: var(--mono); font-size: var(--fs-sm); }
  .hint { color: var(--muted); font-family: var(--sans); font-weight: 400; font-size: 0.85rem; }
  .pre { white-space: pre-wrap; }

  /* Announced by a screen reader, invisible on screen. */
  .sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* --- top bar ------------------------------------------------------------ */

  .topbar {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    padding: 0.6rem 1.25rem;
    border-bottom: var(--rule) solid var(--line);
    background: var(--bg-deep);
    font-family: var(--mono);
    font-size: var(--fs-ui);
  }

  .brand {
    font-family: var(--mono);
    font-weight: 700;
    letter-spacing: 0.02em;
    text-decoration: none;
    color: var(--fg);
  }
  /* A prompt mark, the one terminal flourish in the chrome. */
  .brand::before { content: "~/"; color: var(--accent); font-weight: 400; }

  .topbar nav { display: flex; gap: 1.1rem; }
  .topbar nav a { color: var(--muted); text-decoration: none; }
  .topbar nav a:hover { color: var(--fg); }

  /* Who is signed in, at the far end of the bar. */
  .topbar .session {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    color: var(--muted);
  }
  .whoami { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--muted); }
  .avatar {
    flex: none;
    vertical-align: middle;
    border: var(--rule) solid var(--line-strong);
    border-radius: var(--r-sm);
  }

  .page-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
  }

  /* --- cards and labels --------------------------------------------------- */

  .card {
    background: var(--surface);
    border: var(--rule) solid var(--line);
    border-radius: var(--r);
    padding: 0.9rem 1rem;
    margin-bottom: 0.75rem;
  }
  .card > :last-child { margin-bottom: 0; }
  /* For content that reaches the card's edges, like a table. */
  .card.flush { padding: 0; }

  /* A grid of cards, each a tile of its own. */
  .cards { list-style: none; padding: 0; display: grid; gap: 0.6rem; }
  .cards > .card { margin: 0; }
  .cards > .card:hover { border-color: var(--line-strong); }
  .card-head { display: flex; align-items: center; gap: 0.6rem; }
  /* A tile's title, which is a heading and not a label. */
  .card-head h2 { margin: 0; font-family: var(--mono); font-size: 1rem; font-weight: 700; }
  .card-head h2 a { text-decoration: none; }
  .card-foot {
    display: flex;
    gap: 0.9rem;
    align-items: center;
    margin-top: 0.7rem;
    padding-top: 0.7rem;
    border-top: var(--rule) dotted var(--line-strong);
    font-family: var(--mono);
    font-size: var(--fs-ui);
  }
  .card-foot form { display: inline; }
  .card-foot a { text-decoration: none; }

  /* A card's h2 names its section: a label, not a title. Only the card's
     own, so a heading further down keeps its look. */
  .card > h2,
  .section,
  .stack legend {
    font-family: var(--mono);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    border-bottom: var(--rule) dotted var(--line-strong);
  }
  .card > h2 { margin: 0 0 0.6rem; padding-bottom: 0.45rem; }
  /* A heading of its own, a little larger than a card's. */
  .section,
  .stack legend { font-size: var(--fs-sm); }
  .section { margin-top: 2.2rem; padding: 0 0 0.5rem; }
  .stack legend { width: 100%; margin: 0 0 0.35rem; padding: 0 0 0.5rem; }

  .empty {
    color: var(--muted);
    border: var(--rule) dashed var(--line-strong);
    border-radius: var(--r);
    padding: 2rem;
    text-align: center;
    font-family: var(--mono);
    font-size: var(--fs-ui);
    background: color-mix(in srgb, var(--surface) 55%, transparent);
  }

  /* A rule down the left edge in a tone; give it a box with .card. */
  .callout { border-left: 3px solid var(--accent); }
  /* Aqua rather than gruvbox's green, which sits too close to the yellow of warn. */
  .callout.ok { border-left-color: var(--aqua); }
  .callout.warn { border-left-color: var(--yellow); }
  .callout.danger { border-left-color: var(--red); }
  .callout.quiet { border-left-color: var(--line-strong); }

  .error {
    margin: 0 0 0.75rem;
    background: color-mix(in srgb, var(--red) 12%, transparent);
    border: var(--rule) solid color-mix(in srgb, var(--red) 45%, transparent);
    border-left: 2px solid var(--red);
    color: var(--red);
    border-radius: var(--r);
    padding: 0.7rem 0.9rem;
    font-family: var(--mono);
    font-size: var(--fs-ui);
  }

  /* --- badges ------------------------------------------------------------- */

  .badge {
    display: inline-block;
    padding: 0.05rem 0.4rem;
    border: var(--rule) solid var(--line-strong);
    border-radius: var(--r-sm);
    color: var(--muted);
    font-family: var(--mono);
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    white-space: nowrap;
  }
  .badge.solid { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
  .badge.accent { border-color: var(--accent); color: var(--accent); }
  .badge.ok {
    background: color-mix(in srgb, var(--aqua) 14%, transparent);
    border-color: color-mix(in srgb, var(--aqua) 45%, transparent);
    color: var(--aqua);
  }
  .badge.warn {
    background: color-mix(in srgb, var(--yellow) 16%, transparent);
    border-color: color-mix(in srgb, var(--yellow) 45%, transparent);
    color: var(--yellow);
  }
  .badge.danger {
    background: color-mix(in srgb, var(--red) 12%, transparent);
    border-color: color-mix(in srgb, var(--red) 45%, transparent);
    color: var(--red);
  }

  /* --- buttons and links -------------------------------------------------- */

  /* Opt-in, so a <button> that is a board square or a card stays bare. */
  .button {
    display: inline-block;
    min-height: 2.25rem;
    padding: 0.4rem 0.85rem;
    border: var(--rule) solid var(--accent);
    border-radius: var(--r);
    background: var(--accent);
    color: var(--on-accent);
    font: inherit;
    font-family: var(--mono);
    font-size: var(--fs-ui);
    font-weight: 700;
    line-height: 1.5;
    letter-spacing: 0.01em;
    text-decoration: none;
    cursor: pointer;
  }
  .button:hover { background: var(--accent-dim); border-color: var(--accent-dim); color: var(--on-accent); }
  /* Whatever stands beside the button a form is sent with. */
  .button.secondary { background: var(--surface-raised); border-color: var(--line-strong); color: var(--fg); }
  .button.secondary:hover { border-color: var(--muted); }
  .button:disabled,
  .button.secondary:disabled {
    background: var(--surface-raised);
    border-color: var(--line-strong);
    color: var(--muted);
    cursor: default;
  }

  /* A button or a link set as quiet text, next to the buttons that answer. */
  .link {
    min-height: 0;
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    font-family: var(--mono);
    font-size: var(--fs-ui);
    font-weight: 400;
    letter-spacing: 0;
    text-decoration: none;
    cursor: pointer;
  }
  .link.quiet { color: var(--muted); }
  .link.danger { color: var(--red); }
  .link:hover { color: var(--fg); }

  .actions { display: flex; flex-wrap: wrap; gap: 0.6rem 0.9rem; align-items: center; }

  /* --- forms -------------------------------------------------------------- */

  .check { display: flex; align-items: center; gap: 0.45rem; font-weight: 400; }


  /* Fields under each other. */
  .stack { display: grid; gap: 1rem; max-width: 42rem; }
  .stack .check { margin-bottom: 0.45rem; }
  .stack fieldset { display: grid; gap: 0.4rem; }
  /* The fieldset's gap spaces its rows, a check box's margin included. */
  .stack fieldset > :not(legend),
  .stack fieldset > .check { margin-block: 0; }

  /* Fields beside each other, wrapping when the row runs out. */
  .row { display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; align-items: flex-end; }
  .row > label,
  .row > .grow { flex: 1 1 12rem; }

  /* Radios drawn as a tab bar; the radio stays focusable. */
  .tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    border-bottom: var(--rule) solid var(--line-strong);
  }
  .tabs > .tab {
    display: block;
    margin-bottom: calc(-1 * var(--rule));
    padding: 0.4rem 0.85rem;
    border: var(--rule) solid transparent;
    border-bottom-color: var(--line-strong);
    border-radius: var(--r) var(--r) 0 0;
    color: var(--muted);
    cursor: pointer;
  }
  .tabs > .tab:hover { color: var(--fg); }
  .tabs > .tab:has(input:checked) {
    border-color: var(--line-strong);
    border-bottom-color: var(--bg);
    color: var(--fg);
  }
  .tabs > .tab:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }

  /* --- tables ------------------------------------------------------------- */

  .table { width: 100%; border-collapse: collapse; }
  .table th,
  .table td {
    text-align: left;
    padding: 0.45rem 0.7rem;
    border-bottom: var(--rule) dotted var(--line-strong);
  }
  .table th {
    font-family: var(--mono);
    font-size: var(--fs-xs);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--muted);
    border-bottom-style: solid;
    background: var(--bg-deep);
  }
  .table tbody tr:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
  /* The card's own edge closes a table that ends it. */
  .card > .table:last-child tbody tr:last-child td { border-bottom: 0; }
  /* A table too wide for the window scrolls inside its box. */
  .table-scroll { overflow-x: auto; }

  /* --- toasts ------------------------------------------------------------- */

  .toasts {
    position: fixed;
    right: 1rem;
    bottom: 1rem;
    z-index: 10;
    display: grid;
    gap: 0.5rem;
  }
  .toast {
    padding: 0.55rem 0.85rem;
    border: var(--rule) solid var(--accent);
    border-left: 2px solid var(--accent);
    border-radius: var(--r);
    background: var(--bg-deep);
    color: var(--fg);
    font-family: var(--mono);
    font-size: 0.82rem;
    font-weight: 400;
    box-shadow: var(--shadow);
  }
  .toast.danger { border-color: var(--red); }

  /* --- raster ------------------------------------------------------------- */

  /* A dot grid over a line grid on one 28px pitch, faded out towards the
     edges so the panel has no hard border. On .hero, or any block given
     .raster. */
  .hero,
  .raster {
    position: relative;
    isolation: isolate;
  }
  .hero::before,
  .raster::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    background-image:
      radial-gradient(circle at center, var(--raster-ink) 0 1.1px, transparent 1.2px),
      linear-gradient(to right, var(--raster-ink) 0 1px, transparent 1px),
      linear-gradient(to bottom, var(--raster-ink) 0 1px, transparent 1px);
    background-size: 28px 28px, 112px 112px, 112px 112px;
    background-position: center;
    -webkit-mask-image: radial-gradient(120% 90% at 50% 35%, #000 0%, transparent 72%);
    mask-image: radial-gradient(120% 90% at 50% 35%, #000 0%, transparent 72%);
  }
  .hero { text-align: center; padding: 4.5rem 1rem 3.5rem; }
  .hero h1 { font-size: 2rem; margin: 0 0 0.4rem; }
  .hero p { color: var(--muted); margin: 0 0 1.4rem; }

  /* --- narrow windows ----------------------------------------------------- */

  @media (max-width: 40rem) {
    .topbar { flex-wrap: wrap; gap: 0.5rem 1.25rem; }

    /* A table that becomes a list: without the headings, a cell says itself
       what it holds. */
    .table.stacked thead { display: none; }
    .table.stacked [data-label]::before { content: attr(data-label) ": "; color: var(--muted); }
    .table.stacked,
    .table.stacked tbody,
    .table.stacked tr,
    .table.stacked td { display: block; width: 100%; }
    .table.stacked tr { padding: 0.5rem 0; border-bottom: var(--rule) dotted var(--line-strong); }
    .table.stacked td { padding: 0.15rem 0; border: none; }
    /* The cells have lost their own padding, and a flush card has none. */
    .card.flush .table.stacked tr { padding: 0.5rem 0.7rem; }
    .card > .table.stacked:last-child tbody tr:last-child { border-bottom: 0; }
  }
}
