/*
 * tabs.css
 * Tabs — switching between Views inside a Pane. The panel is the existing
 * View term (frame.css), so this file only adds the strip and the tabs.
 *
 * ── Selected state comes from ARIA, not a class ──────────────────────
 *
 * The active tab is styled through `[aria-selected="true"]`, deliberately
 * not through a `.active` class. With a class you can render a tab that
 * looks selected while announcing itself as unselected — the two states
 * drift the moment someone updates one and forgets the other. Keying the
 * CSS off the ARIA attribute makes that divergence unrepresentable: if it
 * looks selected, it *is* selected as far as assistive tech is concerned.
 *
 * ── What this file does not do (Principle 6) ─────────────────────────
 *
 * Visual treatment is a class; keyboard and focus behavior is a component.
 * Tabs need real behavior, and the app owns it:
 *
 *   - roving tabindex — selected tab tabindex="0", the rest tabindex="-1"
 *   - Left/Right (or Up/Down for a vertical strip) move between tabs
 *   - Home/End jump to first/last
 *   - activating a tab sets aria-selected and unhides its panel
 *
 * Anatomy:
 *
 *   <div class="tabs">
 *     <div class="tablist" role="tablist" aria-label="Invoice sections">
 *       <button class="tab" role="tab" id="t-1"
 *               aria-selected="true" aria-controls="v-1">Details</button>
 *       <button class="tab" role="tab" id="t-2" tabindex="-1"
 *               aria-selected="false" aria-controls="v-2">History</button>
 *     </div>
 *
 *     <article class="view" role="tabpanel" id="v-1"
 *              aria-labelledby="t-1" tabindex="0"> … </article>
 *     <article class="view" role="tabpanel" id="v-2"
 *              aria-labelledby="t-2" tabindex="0" hidden> … </article>
 *   </div>
 *
 * tabindex="0" on the panel matters: panel content is often not focusable,
 * and without it a keyboard user tabs off the strip straight past the
 * content it controls.
 */

.tabs {
  display: block;
}

/*
 * The tone lives here and is passed down as an inheriting property.
 * `.tablist.danger` works; putting the tone on an individual .tab does not,
 * because --bg-mix is element-scoped (see tones.css).
 */
.tablist {
  --tab-accent: var(--bg-mix, var(--color-primary));

  /*
   * The indicator has to be THICKER than the strip it sits on, or a heavy
   * theme draws a 3px rule with a 2px underline over it and the selected
   * tab reads as a gap in the line. One rung above --border-width, and the
   * bleed below is the strip's own weight, so the pair stays correct at
   * any width.
   */
  --tab-indicator-width: calc(var(--border-width) + 1px);

  display:          flex;
  gap:              var(--space-2xs);
  border-block-end: var(--border-width) solid var(--rule);

  /*
   * Many tabs on a narrow screen scroll rather than wrap or squash.
   *
   * overflow-y is the other half and it is not redundant: a box with one axis
   * non-visible promotes the other from `visible` to `auto`. `.tab` then bleeds
   * -1px to sit its underline on the strip's rule, which makes the content one
   * pixel taller than the box — so the strip grew a VERTICAL scrollbar, on
   * every platform that draws a classic one. It reads as a stray widget in the
   * corner rather than as a scrollbar, which is why it survived four versions.
   */
  overflow-x: auto;
  overflow-y: hidden;
}

.tab {
  flex-shrink:  0;
  display:      inline-flex;
  align-items:  center;
  gap:          var(--space-xs);

  /* <button> reset */
  background: none;
  border:     none;
  font:       inherit;
  cursor:     pointer;

  padding:          var(--space-sm) var(--space-xl);
  font-size:        var(--text-md);
  font-weight:      600;
  color:            var(--ink-soft);
  white-space:      nowrap;
  border-block-end: var(--tab-indicator-width) solid transparent;
  /* Pull the underline down onto the tablist's own rule. */
  margin-block-end: calc(var(--border-width) * -1);

  transition: color var(--motion-fast), border-color var(--motion-fast),
              background var(--motion-fast);
}

.tab:hover {
  color: var(--ink);
}

/*
 * The ring itself is in focus.css (inset, because the tablist scrolls).
 * What stays here is the shape it traces: a tab is square while it rests,
 * so its 2px underline sits flat on the tablist rule, and rounds only for
 * the ring — outline follows border-radius.
 */
.tab:focus-visible {
  border-radius: var(--btn-radius);
}

.tab[aria-selected="true"] {
  color:                  var(--tab-accent);
  border-block-end-color: var(--tab-accent);
}

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

/* ── Stretch — tabs share the width equally ──────────────────────── */
.tablist.stretch .tab {
  flex:            1;
  justify-content: center;
}

/* ── Pills — a filled strip with no baseline rule ────────────────── */
.tablist.pills {
  border-block-end: none;
  gap:              var(--space-xs);
}
.tablist.pills .tab {
  border-block-end: none;
  margin-block-end: 0;
  border-radius:    var(--btn-radius);
  padding:          var(--space-xs) var(--space-lg);
}
.tablist.pills .tab:hover:not([aria-selected="true"]) {
  background: var(--surface-sunken);
}
.tablist.pills .tab[aria-selected="true"] {
  background: color-mix(in srgb, var(--tab-accent) 12%, var(--surface));
  color:      var(--tab-accent);
}

/* Panels sit below the strip with a little air. */
.tabs > .view {
  padding-block-start: var(--space-2xl);
}

/*
 * ── Vertical — the strip runs down the side ──────────────────────────
 *
 *   <div class="tabs vertical">
 *     <div class="tablist" role="tablist" aria-orientation="vertical" …>
 *
 * For settings screens and anything with more than about six sections,
 * where a horizontal strip either wraps or scrolls and the labels are too
 * long to abbreviate.
 *
 * `aria-orientation="vertical"` on the tablist is not decorative: it tells
 * assistive tech which arrow keys to expect, and it changes what the app
 * has to implement — **Up/Down move between tabs, not Left/Right**. Left
 * and Right should do nothing. That is still the app's job (Principle 6);
 * this file only turns the strip.
 */
.tabs.vertical {
  display:     flex;
  align-items: flex-start;
  gap:         var(--space-4xl);
}

.tabs.vertical .tablist {
  flex-direction:    column;
  align-items:       stretch;
  gap:               var(--space-3xs);

  /* The rule moves from under the strip to beside it. */
  border-block-end:  none;
  border-inline-end: var(--border-width) solid var(--rule);

  /*
   * A vertical strip grows downward; it does not need to scroll on either
   * axis. BOTH have to be restated: leaving `overflow-y: hidden` standing
   * would promote this `visible` back to `auto`, and `.tab`'s -1px inline
   * bleed would then draw a horizontal scrollbar on a vertical strip — the
   * same defect the horizontal case has, turned ninety degrees.
   */
  overflow:        visible;
  flex-shrink:     0;
  min-inline-size: 11rem;
}

.tabs.vertical .tab {
  /* The indicator moves from the bottom edge to the inline end. */
  border-block-end:   none;
  margin-block-end:   0;
  border-inline-end:  var(--tab-indicator-width) solid transparent;
  margin-inline-end:  calc(var(--border-width) * -1);

  justify-content: flex-start;
  text-align:      start;
  /* Long section names wrap instead of scrolling out of reach. */
  white-space:     normal;
}

.tabs.vertical .tab[aria-selected="true"] {
  border-inline-end-color: var(--tab-accent);
}

.tabs.vertical > .view {
  flex: 1;
  /*
   * A flex item defaults to min-inline-size: auto, so a wide table or a
   * long <pre> inside the panel pushes the track wider than the container
   * instead of scrolling inside it — and the whole page then scrolls
   * sideways. Same single line, same reason, as .screen in frame.css.
   */
  min-inline-size:     0;
  padding-block-start: 0;
}

/*
 * A vertical pills strip has no side rule to hang the indicator on, so
 * the selected pill keeps the filled treatment and drops the border.
 */
.tabs.vertical .tablist.pills {
  border-inline-end: none;
}
.tabs.vertical .tablist.pills .tab {
  border-inline-end: none;
  margin-inline-end: 0;
}
