/* ==========================================================================
   retro-desktop-theme / components
   --------------------------------------------------------------------------
   Five components for the content that lives INSIDE a window: button, panel,
   badge, field, list. The window itself, the icons, the taskbar and the
   programs menu are not here; they are the shell, and they live in
   shell/shell.css. That split is the point of this theme: these components
   would work on an ordinary page, and the shell would work around different
   components.

   Every color here is a var() reference to tokens.css. There is not one
   color literal in this file, which is what makes retheming a matter of
   editing one file rather than auditing five.

   The class names follow the shadcn shape: one base class carrying the
   structure, one variant class carrying the intent (rd-btn + rd-btn-primary).

   ONE THING IS MISSING ON PURPOSE: A COLORED BUTTON. This era's dialogs were
   gray, all of them, and intent was carried by the extra black ring around
   the default button and by the wording on it. So rd-btn-primary is the
   default-button ring rather than a colored fill, and rd-btn-destructive is
   maroon ink on the same gray face rather than a red slab. If your page needs
   a louder call to action than the era had, --rd-accent is one token away;
   what you would be buying is a later decade, and the theme would rather you
   made that trade on purpose.

   Requires tokens.css to be loaded first. Load it explicitly rather than
   letting this file pull it in, so the dependency is visible at the call
   site:

     <link rel="stylesheet" href="tokens/tokens.css" />
     <link rel="stylesheet" href="components/components.css" />
   ========================================================================== */

/* --------------------------------------------------------------------------
   Shared focus. A dotted rectangle drawn inside the control, which is how
   this era drew focus and is still unmistakable. Two pixels rather than the
   era's one, because a one-pixel dotted ring is a hairline on a high-density
   screen.
   -------------------------------------------------------------------------- */
.rd-btn:focus-visible,
.rd-input:focus-visible,
.rd-focusable:focus-visible {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

/* ==========================================================================
   BUTTON
   Variants: rd-btn-primary, rd-btn-default, rd-btn-quiet, rd-btn-destructive
   Sizes:    rd-btn-sm, (base)
   ========================================================================== */
.rd-btn {
  /* 44px minimum on both axes. The era would have drawn this at 23px; a
     real thumb has not changed size since, and this is the floor the rest
     of the collection holds. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--rd-space-2);
  min-height: 44px;
  padding: var(--rd-space-2) var(--rd-space-6);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-body);
  font-weight: var(--rd-weight-body);
  line-height: var(--rd-leading-snug);
  text-decoration: none;
  white-space: nowrap;

  color: var(--rd-ink);
  background: var(--rd-face);
  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise);
  cursor: pointer;
}

/* The press is the bevel inverting and the label moving one pixel down and
   right, which is exactly what this era did and is the reason a physical
   metaphor needs no transition to feel mechanical. No transform, no
   animation: the state change is instant, as it was. */
.rd-btn:active:not(:disabled) {
  box-shadow: var(--rd-sink);
  padding: calc(var(--rd-space-2) + 1px) calc(var(--rd-space-6) - 1px)
    calc(var(--rd-space-2) - 1px) calc(var(--rd-space-6) + 1px);
}

/* Disabled: gray type with a white emboss under it, which is exactly how
   this era drew an unavailable label. The gray measures 2.17:1 on the face,
   and that is allowed because WCAG exempts inactive components from the
   contrast minimum; the emboss is there because the era used it and because
   an exemption is not a reason to make something needlessly hard to read. */
.rd-btn:disabled,
.rd-btn[aria-disabled="true"] {
  color: var(--rd-bevel-shadow);
  text-shadow: 1px 1px 0 var(--rd-bevel-hi);
  cursor: not-allowed;
}

/* The default button: an extra black ring outside the bevel, drawn with a
   spread shadow so it costs no layout. This is the era's whole vocabulary
   for "this is the one you probably want". */
.rd-btn-primary {
  box-shadow: var(--rd-raise), 0 0 0 1px var(--rd-bevel-dark);
  font-weight: var(--rd-weight-bold);
}

.rd-btn-primary:active:not(:disabled) {
  box-shadow: var(--rd-sink), 0 0 0 1px var(--rd-bevel-dark);
}

.rd-btn-default {
  /* The base treatment, named so the markup can say which it meant. */
  box-shadow: var(--rd-raise);
}

/* The quiet button sits flat until hovered, which is how the reader learns
   it was a button all along. The era used this for toolbar buttons and it is
   the closest thing here to a ghost. */
.rd-btn-quiet {
  background: transparent;
  box-shadow: none;
}

.rd-btn-quiet:hover {
  background: var(--rd-face);
  box-shadow: var(--rd-raise-thin);
}

.rd-btn-destructive {
  color: var(--rd-destructive);
  font-weight: var(--rd-weight-bold);
}

.rd-btn-sm {
  min-height: 32px;
  padding: var(--rd-space-1) var(--rd-space-3);
  font-size: var(--rd-text-sm);
}

.rd-btn-sm:active:not(:disabled) {
  padding: calc(var(--rd-space-1) + 1px) calc(var(--rd-space-3) - 1px)
    calc(var(--rd-space-1) - 1px) calc(var(--rd-space-3) + 1px);
}

/* ==========================================================================
   PANEL
   The era's group box: an etched frame with a title on it. Variants: (base),
   rd-panel-raised for the card that sticks out instead of going in.
   Parts: rd-panel-title, rd-panel-body.
   ========================================================================== */
.rd-panel {
  display: flex;
  flex-direction: column;
  gap: var(--rd-space-2);
  padding: var(--rd-space-4);

  background: var(--rd-face);
  color: var(--rd-ink);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-sink-thin);
}

.rd-panel-raised {
  box-shadow: var(--rd-raise);
}

.rd-panel-title {
  margin: 0;
  font-size: var(--rd-text-h3);
  font-weight: var(--rd-weight-bold);
  line-height: var(--rd-leading-snug);
}

.rd-panel-body {
  margin: 0;
  color: var(--rd-ink-muted);
  font-size: var(--rd-text-body);
  line-height: var(--rd-leading-body);
}

/* ==========================================================================
   BADGE
   Variants: rd-badge-neutral, rd-badge-success, rd-badge-info,
             rd-badge-warning, rd-badge-danger
   ========================================================================== */
.rd-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--rd-space-1);
  padding: var(--rd-space-1) var(--rd-space-2);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-xs);
  font-weight: var(--rd-weight-bold);
  line-height: var(--rd-leading-snug);
  letter-spacing: var(--rd-tracking-wide);
  text-transform: uppercase;

  /* Full black on every fill. Meaning lives in the hue; legibility never
     depends on it. */
  color: var(--rd-ink);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
  white-space: nowrap;
}

.rd-badge-neutral {
  background: var(--rd-face);
}

.rd-badge-success {
  background: var(--rd-fill-success);
}

.rd-badge-info {
  background: var(--rd-fill-info);
}

.rd-badge-warning {
  background: var(--rd-fill-warning);
}

.rd-badge-danger {
  background: var(--rd-fill-danger);
}

/* ==========================================================================
   FIELD
   Parts:  rd-field, rd-label, rd-input, rd-hint, rd-error
   States: default, :focus, aria-invalid="true", :disabled
   A field goes IN. That is the whole reason the bevel tokens come in a pair:
   a control you press is raised and a control you type into is sunken, and
   the reader has known which is which since before this era.
   ========================================================================== */
.rd-field {
  display: flex;
  flex-direction: column;
  gap: var(--rd-space-2);
}

.rd-label {
  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-sm);
  font-weight: var(--rd-weight-bold);
  color: var(--rd-ink);
}

.rd-input {
  /* 16px minimum, which is what stops iOS Safari zooming on focus. */
  width: 100%;
  min-height: 44px;
  padding: var(--rd-space-2) var(--rd-space-3);

  font-family: var(--rd-font-ui);
  font-size: var(--rd-text-body);
  color: var(--rd-ink);
  background: var(--rd-surface);

  border: 0;
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-sink);
}

.rd-input::placeholder {
  color: var(--rd-ink-muted);
}

.rd-input:focus {
  outline: var(--rd-ring-width) var(--rd-ring-style) var(--rd-ring);
  outline-offset: calc(-1 * var(--rd-ring-inset));
}

.rd-input[aria-invalid="true"] {
  box-shadow: var(--rd-sink), 0 0 0 1px var(--rd-destructive);
}

.rd-input:disabled {
  background: var(--rd-face);
  color: var(--rd-ink-muted);
  cursor: not-allowed;
}

.rd-hint {
  font-size: var(--rd-text-sm);
  color: var(--rd-ink-muted);
}

.rd-error {
  font-size: var(--rd-text-sm);
  font-weight: var(--rd-weight-bold);
  color: var(--rd-destructive);
}

/* Textarea inherits the input treatment. */
.rd-input:where(textarea) {
  min-height: 120px;
  resize: vertical;
}

/* ==========================================================================
   LIST
   Settings-style rows: a name, an optional description, a value or control
   at the end. The row divider is the era's etched line, one gray hairline
   with one white hairline under it, which is the only job the hairline token
   has in this theme.
   Parts: rd-list, rd-list-row, rd-list-name, rd-list-desc, rd-list-end
   ========================================================================== */
.rd-list {
  margin: 0;
  padding: 0;
  list-style: none;
  background: var(--rd-surface);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-sink-thin);
}

.rd-list-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rd-space-4);
  padding: var(--rd-space-3) var(--rd-space-4);
}

.rd-list-row + .rd-list-row {
  border-top: var(--rd-hairline) solid var(--rd-bevel-shadow);
  box-shadow: inset 0 var(--rd-hairline) 0 0 var(--rd-bevel-hi);
}

.rd-list-name {
  font-weight: var(--rd-weight-bold);
  color: var(--rd-ink);
}

.rd-list-desc {
  display: block;
  font-weight: var(--rd-weight-body);
  font-size: var(--rd-text-sm);
  color: var(--rd-ink-muted);
}

.rd-list-end {
  flex: none;
  font-family: var(--rd-font-mono);
  font-size: var(--rd-text-sm);
  color: var(--rd-ink-muted);
}

/* A keyboard hint chip, for the shell's keyboard story. Real text in a kbd
   element, not an image of a key, and raised because a key sticks out. */
.rd-kbd {
  display: inline-block;
  padding: 0 var(--rd-space-2);
  font-family: var(--rd-font-mono);
  font-size: var(--rd-text-xs);
  line-height: 1.9;
  color: var(--rd-ink);
  background: var(--rd-face);
  border-radius: var(--rd-radius);
  box-shadow: var(--rd-raise-thin);
}
