/* ==========================================================================
   vivaocean-theme / components
   --------------------------------------------------------------------------
   Eight components for the content that lives INSIDE the window: prose,
   button, panel, badge, field, list, table, code. The window itself, the
   rails, the menu and the water are not here; they are the shell and the
   scene, and they live in shell/ and scene/. That split is the point of the
   theme: these components would work on an ordinary page, and the shell
   would work around different components.

   The list is longer than the fleet's usual five, and the extra three are
   not padding. A shell that holds a whole SaaS site rather than one card
   has to render a comparison table, a documentation code block and a page
   of prose, and leaving those to each consuming page is how a theme ends up
   with nine pages that each invented their own <h1>.

   There is not one color literal in this file. Every color, every duration
   and every piece of spacing is a var() reference to tokens.css.

   Five declarations carry a bare length, and they are all the same kind:
   the 44px control minimums on the button and the field (WCAG 2.5.8), the
   36px small-button minimum, the 120px textarea floor, and the 1px press
   travel. The target minimums stay literal on purpose, because a token
   invites a re-skin to lower an accessibility floor.

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

   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. The accent ring, offset outside the element. Everything in
   this file sits on a light surface, so one color is enough here; the
   two-color ring in tokens.css is for the shell's elements, which sit on
   water.
   -------------------------------------------------------------------------- */
.vo-btn:focus-visible,
.vo-input:focus-visible,
.vo-focusable:focus-visible {
  outline: var(--vo-ring-width) solid var(--vo-accent);
  outline-offset: var(--vo-ring-offset);
}

/* ==========================================================================
   PROSE
   The type scale as classes rather than as element selectors, so a
   consuming page can use them on whatever element the outline actually
   calls for. Parts: vo-h1, vo-h2, vo-h3, vo-lead, vo-prose, vo-fine.
   ========================================================================== */
.vo-h1 {
  margin: 0 0 var(--vo-space-4);
  font-size: var(--vo-text-display);
  font-weight: var(--vo-weight-display);
  line-height: var(--vo-leading-tight);
  letter-spacing: var(--vo-tracking-tight);
  color: var(--vo-ink);
  text-wrap: balance;
}

.vo-h2 {
  margin: var(--vo-space-12) 0 var(--vo-space-3);
  font-size: var(--vo-text-h1);
  font-weight: var(--vo-weight-display);
  line-height: var(--vo-leading-tight);
  letter-spacing: var(--vo-tracking-tight);
  color: var(--vo-ink);
  text-wrap: balance;
}

.vo-h3 {
  margin: var(--vo-space-8) 0 var(--vo-space-2);
  font-size: var(--vo-text-h3);
  font-weight: var(--vo-weight-bold);
  line-height: var(--vo-leading-snug);
  letter-spacing: var(--vo-tracking-tight);
  color: var(--vo-ink);
}

.vo-lead {
  max-width: var(--vo-measure);
  margin: 0 0 var(--vo-space-6);
  font-size: var(--vo-text-lead);
  line-height: var(--vo-leading-body);
  color: var(--vo-ink-muted);
}

/* The measure, applied to a wrapper rather than to every paragraph, so a
   figure or a table inside it can opt out by sitting outside it. */
.vo-prose {
  max-width: var(--vo-measure);
}

.vo-prose p {
  margin: 0 0 var(--vo-space-4);
}

.vo-fine {
  margin: var(--vo-space-6) 0 0;
  font-size: var(--vo-text-sm);
  color: var(--vo-ink-muted);
}

/* A link inside the window. The accent, underlined, because on a page this
   dense a color-only link is a guess. */
.vo-window-body a:not(.vo-btn):not(.vo-brand):not(.vo-rail-item) {
  color: var(--vo-accent);
  text-underline-offset: 0.15em;
}

/* ==========================================================================
   BUTTON
   Variants: vo-btn-primary, vo-btn-default, vo-btn-ghost, vo-btn-destructive
   Sizes:    vo-btn-sm, (base)
   ========================================================================== */
.vo-btn {
  /* 44px minimum on both axes. Anything smaller fails on a real thumb. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--vo-space-2);
  min-height: 44px;
  padding: var(--vo-space-3) var(--vo-space-6);

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

  border: var(--vo-border-width) solid var(--vo-border-strong);
  border-radius: var(--vo-radius);
  box-shadow: var(--vo-shadow-sm);
  cursor: pointer;

  transition:
    transform var(--vo-duration) var(--vo-ease),
    box-shadow var(--vo-duration) var(--vo-ease);
}

/* One pixel of travel and the shadow going flat: a click that feels
   mechanical without performing. */
.vo-btn:active:not(:disabled) {
  transform: translateY(1px);
  box-shadow: none;
}

.vo-btn:disabled,
.vo-btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.vo-btn-primary {
  background: var(--vo-accent);
  color: var(--vo-accent-ink);
  border-color: var(--vo-accent);
}

.vo-btn-default {
  background: var(--vo-surface);
  color: var(--vo-ink);
}

.vo-btn-default:hover {
  background: var(--vo-chrome);
}

.vo-btn-destructive {
  background: var(--vo-destructive);
  color: var(--vo-destructive-ink);
  border-color: var(--vo-destructive);
}

/* The ghost sits flat until hovered, which is how the reader learns it was
   a button all along. */
.vo-btn-ghost {
  background: transparent;
  color: var(--vo-ink);
  border-color: transparent;
  box-shadow: none;
}

.vo-btn-ghost:hover {
  background: var(--vo-surface-muted);
}

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

/* ==========================================================================
   PANEL
   A surface inside the window. Variants: (base), vo-panel-muted.
   Parts: vo-panel-title, vo-panel-body.
   ========================================================================== */
.vo-panel {
  display: flex;
  flex-direction: column;
  gap: var(--vo-space-2);
  padding: var(--vo-space-4);

  background: var(--vo-surface);
  color: var(--vo-ink);
  border: var(--vo-border-width) solid var(--vo-border);
  border-radius: var(--vo-radius);
  box-shadow: var(--vo-shadow-sm);
}

.vo-panel-muted {
  background: var(--vo-surface-muted);
  box-shadow: none;
}

.vo-panel-title {
  margin: 0;
  font-size: var(--vo-text-h3);
  font-weight: var(--vo-weight-bold);
  line-height: var(--vo-leading-snug);
  letter-spacing: var(--vo-tracking-tight);
}

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

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

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

  /* Ink on every fill. Meaning lives in the hue; legibility never depends
     on it. */
  color: var(--vo-ink);
  border: var(--vo-border-width) solid var(--vo-border);
  border-radius: var(--vo-radius-tight);
  white-space: nowrap;
}

.vo-badge-neutral {
  background: var(--vo-surface-muted);
}

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

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

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

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

/* ==========================================================================
   FIELD
   Parts:  vo-field, vo-label, vo-input, vo-hint, vo-error
   States: default, :focus, aria-invalid="true", :disabled
   ========================================================================== */
.vo-field {
  display: flex;
  flex-direction: column;
  gap: var(--vo-space-2);
}

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

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

  font-family: var(--vo-font-sans);
  font-size: var(--vo-text-body);
  color: var(--vo-ink);
  background: var(--vo-surface);

  border: var(--vo-border-width) solid var(--vo-border-strong);
  border-radius: var(--vo-radius);
}

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

.vo-input:focus {
  outline: var(--vo-ring-width) solid var(--vo-accent);
  outline-offset: var(--vo-ring-offset);
}

.vo-input[aria-invalid="true"] {
  border-color: var(--vo-destructive);
}

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

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

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

.vo-input:where(textarea) {
  min-height: 120px;
  resize: vertical;
}

/* ==========================================================================
   LIST
   Settings-style rows: a name, an optional description, a value at the end.
   Parts: vo-list, vo-list-row, vo-list-name, vo-list-desc, vo-list-end
   ========================================================================== */
.vo-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border: var(--vo-border-width) solid var(--vo-border);
  border-radius: var(--vo-radius);
  background: var(--vo-surface);
  overflow: hidden;
}

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

.vo-list-row + .vo-list-row {
  border-top: var(--vo-border-width) solid var(--vo-border);
}

.vo-list-name {
  font-weight: var(--vo-weight-medium);
  color: var(--vo-ink);
}

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

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

/* ==========================================================================
   TABLE
   The comparison table a pricing page cannot do without. Wrapped in
   vo-table-scroll so a wide table scrolls inside the window rather than
   widening it; the window has one job and it is not horizontal scrolling.
   Parts: vo-table-scroll, vo-table, vo-table-note
   ========================================================================== */
.vo-table-scroll {
  overflow-x: auto;
  margin: var(--vo-space-6) 0;
  border: var(--vo-border-width) solid var(--vo-border);
  border-radius: var(--vo-radius);
}

.vo-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--vo-text-sm);
  background: var(--vo-surface);
}

.vo-table caption {
  padding: var(--vo-space-3) var(--vo-space-4);
  text-align: left;
  font-weight: var(--vo-weight-bold);
  color: var(--vo-ink);
  background: var(--vo-chrome);
  border-bottom: var(--vo-border-width) solid var(--vo-border);
}

.vo-table th,
.vo-table td {
  padding: var(--vo-space-3) var(--vo-space-4);
  text-align: left;
  vertical-align: top;
  border-bottom: var(--vo-border-width) solid var(--vo-border);
}

.vo-table thead th {
  color: var(--vo-ink);
  font-weight: var(--vo-weight-bold);
  background: var(--vo-surface-muted);
  white-space: nowrap;
}

.vo-table tbody th {
  color: var(--vo-ink);
  font-weight: var(--vo-weight-medium);
}

.vo-table td {
  color: var(--vo-ink-muted);
}

.vo-table tbody tr:last-child th,
.vo-table tbody tr:last-child td {
  border-bottom: 0;
}

.vo-table-note {
  margin: 0;
  font-size: var(--vo-text-sm);
  color: var(--vo-ink-muted);
}

/* ==========================================================================
   CODE
   A block for documentation and an inline voice for a path or a flag. Both
   are real text in real elements, never a picture of code.
   Parts: vo-code (block), vo-code-inline, vo-kbd
   ========================================================================== */
.vo-code {
  overflow-x: auto;
  margin: var(--vo-space-4) 0;
  padding: var(--vo-space-4);

  background: var(--vo-surface-muted);
  border: var(--vo-border-width) solid var(--vo-border);
  border-radius: var(--vo-radius);

  font-family: var(--vo-font-mono);
  font-size: var(--vo-text-sm);
  line-height: var(--vo-leading-body);
  color: var(--vo-ink);
}

.vo-code-inline {
  padding: 0 var(--vo-space-1);
  font-family: var(--vo-font-mono);
  font-size: 0.9em;
  color: var(--vo-ink);
  background: var(--vo-surface-muted);
  border-radius: var(--vo-radius-tight);
}

/* A keyboard hint. Real text in a kbd element, not an image of a key. */
.vo-kbd {
  display: inline-block;
  padding: 0 var(--vo-space-2);
  font-family: var(--vo-font-mono);
  font-size: var(--vo-text-xs);
  line-height: 1.8;
  color: var(--vo-ink);
  background: var(--vo-chrome);
  border: var(--vo-border-width) solid var(--vo-border-strong);
  border-bottom-width: 2px;
  border-radius: var(--vo-radius-tight);
}
