/* -- Tabs component -------------------------------------------- */

@layer components {
  /* -- Default (pill) variant ----------------------------------- */
  /* An inline GRID, one minmax(0, max-content) track per tab: when the row
     is too narrow, every track grows from 0 at the same pace, so short labels
     reach their full width first and only the long ones are cut ("…") -
     flex-shrink would clip a short "Churn" as eagerly as a long label. */
  .tab-list {
    display: inline-grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(0, max-content);
    align-items: center;
    /* never wider than its container: the triggers shrink and ellipsize */
    max-width: 100%;
    min-width: 0;
    box-sizing: border-box;
    background: var(--muted);
    border-radius: var(--radius-lg);
    padding: 0.25rem;
    gap: 0.125rem;

    /* -- Sizes: trigger font + padding scale (set data-size on .tab-list).
       :where() keeps these at one class of specificity over the plain
       .tab-trigger base. md == each variant's own base padding, so md is
       selectable everywhere without a visual change. Paddings are logical
       (block / inline), so they turn with the vertical labels of side tabs.
       The line variant's trigger base (0.5rem/1rem, nested in
       [data-variant="line"]) outranks the :where() rules, so its overrides
       are un-:where()'d (two attrs). */
    &:where([data-size="xs"]) .tab-trigger { padding-block: 0.25rem; padding-inline: 0.5rem;    font-size: 0.75rem; }
    &:where([data-size="sm"]) .tab-trigger { padding-block: 0.3125rem; padding-inline: 0.625rem; font-size: 0.8125rem; }
    &:where([data-size="md"]) .tab-trigger { padding-block: 0.375rem; padding-inline: 0.75rem;   font-size: 0.875rem; }
    &:where([data-size="lg"]) .tab-trigger { padding-block: 0.5rem; padding-inline: 1rem;       font-size: 1rem; }
    &:where([data-size="xl"]) .tab-trigger { padding-block: 0.625rem; padding-inline: 1.25rem;  font-size: 1.125rem; }
    &[data-variant="line"][data-size="xs"] .tab-trigger { padding-block: 0.25rem; padding-inline: 0.5rem; }
    &[data-variant="line"][data-size="sm"] .tab-trigger { padding-block: 0.375rem; padding-inline: 0.75rem; }
    &[data-variant="line"][data-size="md"] .tab-trigger { padding-block: 0.5rem; padding-inline: 1rem; }
    &[data-variant="line"][data-size="lg"] .tab-trigger { padding-block: 0.625rem; padding-inline: 1.25rem; }
    &[data-variant="line"][data-size="xl"] .tab-trigger { padding-block: 0.75rem; padding-inline: 1.5rem; }

    /* -- Line variant --------------------------------------------- */
    &[data-variant="line"] {
      background: transparent;
      border-radius: 0;
      padding: 0;
      gap: 0;
      border-bottom: 1px solid var(--border);

      & .tab-trigger {
        border-radius: 0;
        padding-block: 0.5rem;
        padding-inline: 1rem;
        border-bottom: 2px solid transparent;
        margin-bottom: -1px;

        &[aria-selected="true"] {
          background: transparent;
          color: var(--foreground);
          border-bottom-color: var(--primary);
          box-shadow: none;
        }
      }
    }

    /* -- Vertical orientation ------------------------------------ */
    &[aria-orientation="vertical"] {
      grid-auto-flow: row;
      grid-auto-rows: minmax(0, max-content);
      grid-auto-columns: auto;
      align-items: stretch;
      width: auto;

      & .tab-trigger { text-align: start; }
    }
  }

  /* A trigger is a BLOCK box (not inline-flex): text-overflow only works on
     a block container's own line, and a flex container would wrap a bare
     label in an anonymous box that never ellipsizes. Icons and emoji ride
     inline in front of the label - svg / img / .tab-icon - so plain
     <button>Label</button> markup keeps working and a long label ends in "…"
     when the list runs out of room (horizontal and vertical alike). */
  .tab-trigger {
    display: block;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: center;
    line-height: 1.25rem;
    padding-block: 0.375rem;
    padding-inline: 0.75rem;
    border-radius: calc(var(--radius) * 0.6);
    font-size: 0.875rem;
    font-weight: 500;
    border: none;
    background: transparent;
    color: var(--muted-foreground);
    cursor: pointer;
    transition: all 150ms ease;
    outline: none;

    & :is(svg, img, .tab-icon) {
      display: inline-block;
      vertical-align: middle;
      margin-inline-end: 0.5em;
      line-height: 1;
    }
    & :is(svg, img) {
      inline-size: 1em;
      block-size: 1em;
      translate: 0 -0.0625em;
    }

    &[aria-selected="true"] {
      background: var(--background);
      color: var(--foreground);
      box-shadow: 0 1px 3px oklch(0 0 0 / 0.08), 0 0 0 1px var(--border);
    }

    &:focus-visible {
      outline: 2px solid var(--ring);
      outline-offset: 2px;
    }

    &:disabled {
      cursor: not-allowed;
      opacity: 0.5;
    }
  }

  /* -- Layout: which side of the panel the tabs sit on ---------
     data-side="top|bottom|left|right" on .tabs (default top; a vertical
     tablist without data-side keeps the old settings-nav layout) and
     data-align="start|center|end" for where the tabs cluster along that
     edge (top/bottom: start = left; left/right: start = top). The DOM order
     never changes - tablist first - only the visual side. :where() keeps the
     side selectors at zero specificity, so variants override them cleanly. */
  .tabs {
    display: flex;
    flex-direction: column;
    min-width: 0;

    & > .tab-list { align-self: flex-start; }
    &[data-align="center"] > .tab-list { align-self: center; }
    &[data-align="end"] > .tab-list { align-self: flex-end; }

    &:where([data-side="bottom"]) {
      & > .tab-list { order: 2; }
      & > .tab-content { margin-top: 0; margin-bottom: 0.75rem; }
    }

    /* the older aria-orientation-only markup: a settings nav beside the
       panel, horizontal labels (ellipsized past 40% of the width) */
    &:where(:not([data-side]):has(> .tab-list[aria-orientation="vertical"])) {
      flex-direction: row;
      align-items: flex-start;
      gap: 1rem;

      & > .tab-list { max-width: 40%; }
      & > .tab-content { margin: 0; flex: 1; min-width: 0; }
      &:dir(rtl) { flex-direction: row-reverse; }
    }

    /* data-side left / right: a two-column grid. The tab column has
       height 0 + min-height 100% - it adds nothing to the row, so the PANEL
       decides the height and the column fills it: when the labels need more
       room than the panel is tall, they shrink and ellipsize. left / right
       are physical sides, also in RTL. */
    &:where([data-side="left"], [data-side="right"]) {
      display: grid;
      grid-template-columns: auto minmax(0, 1fr);
      grid-template-areas: "list panel";
      column-gap: 1rem;

      & > .tab-list {
        grid-area: list;
        grid-auto-flow: row;
        grid-auto-rows: minmax(0, max-content);
        grid-auto-columns: auto;
        align-items: stretch;
        align-self: stretch;
        align-content: start;
        height: 0;
        min-height: 100%;
        max-width: none;
      }
      &[data-align="center"] > .tab-list { align-content: center; }
      &[data-align="end"] > .tab-list { align-content: end; }
      & > .tab-content { grid-area: panel; margin: 0; min-width: 0; }

      /* the labels run vertically along the panel edge - right-hand tabs
         read top to bottom, left-hand ones bottom to top (like book spines;
         sideways-lr where supported, else top to bottom too). The logical
         trigger paddings turn with the writing mode, and icons and emoji
         turn with the label: text-orientation: sideways lays emoji on
         their side like any other glyph, and svg / img (which a vertical
         line would keep upright) rotate a quarter turn. */
      & > .tab-list .tab-trigger {
        writing-mode: vertical-rl;
        text-orientation: sideways;
        text-align: center;

        & :is(svg, img) { rotate: 90deg; }
      }
    }
    &:where([data-side="right"]) {
      grid-template-columns: minmax(0, 1fr) auto;
      grid-template-areas: "panel list";
    }
    &:where([data-side="left"]):dir(rtl) {
      grid-template-columns: minmax(0, 1fr) auto;
      grid-template-areas: "panel list";
    }
    &:where([data-side="right"]):dir(rtl) {
      grid-template-columns: auto minmax(0, 1fr);
      grid-template-areas: "list panel";
    }
    @supports (writing-mode: sideways-lr) {
      /* sideways-lr lays emoji on their side, but svg / img keep their
         orientation: a quarter turn back, so they point up the line */
      &:where([data-side="left"]) > .tab-list .tab-trigger {
        writing-mode: sideways-lr;

        & :is(svg, img) { rotate: -90deg; }
      }
    }
  }

  /* line variant: the rule sits on the edge that faces the panel (physical
     sides for left / right - the trigger's own writing mode is vertical, so
     its logical inline-end would point down) */
  .tabs[data-side="bottom"] > .tab-list[data-variant="line"] {
    border-bottom: none;
    border-top: 1px solid var(--border);

    & .tab-trigger {
      border-bottom: none;
      border-top: 2px solid transparent;
      margin-bottom: 0;
      margin-top: -1px;

      &[aria-selected="true"] { border-top-color: var(--primary); }
    }
  }
  .tabs:is([data-side="left"], [data-side="right"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"])) > .tab-list[data-variant="line"] {
    border-bottom: none;

    & .tab-trigger { border-bottom: none; margin-bottom: 0; }
  }
  .tabs:is([data-side="left"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"])) > .tab-list[data-variant="line"] {
    border-right: 1px solid var(--border);

    & .tab-trigger {
      border-right: 2px solid transparent;
      margin-right: -1px;

      &[aria-selected="true"] { border-right-color: var(--primary); }
    }
  }
  .tabs[data-side="right"] > .tab-list[data-variant="line"] {
    border-left: 1px solid var(--border);

    & .tab-trigger {
      border-left: 2px solid transparent;
      margin-left: -1px;

      &[aria-selected="true"] { border-left-color: var(--primary); }
    }
  }

  /* -- Attached variant: folder tabs joined to the panel's card --
     data-variant="attached" on the .tab-list; each panel holds a .card.
     The selected tab takes the card surface and covers the card's border
     where they meet, so tab and card read as one shape. The card corner the
     tabs grow from is squared; every ROUNDED corner keeps the tabs a card
     radius (--radius-xl) away, so no tab ever sits on a curve - start keeps
     the far end clear, end the near one, center both. */
  .tab-list[data-variant="attached"] {
    background: transparent;
    border-radius: 0;
    padding: 0;
    gap: 0.25rem;
    position: relative;
    z-index: 1;

    & .tab-trigger {
      border: 1px solid var(--border);
      background: var(--muted);
      box-shadow: none;
      border-radius: var(--radius-md) var(--radius-md) 0 0;

      &[aria-selected="true"] {
        background: var(--card);
        color: var(--card-foreground);
        box-shadow: none;
        border-bottom-color: var(--card);
      }
    }
  }
  .tabs:has(> .tab-list[data-variant="attached"]) {
    gap: 0;
    column-gap: 0;

    & > .tab-content { margin: 0; }

    /* top (default) / bottom: the tabs overlap the card border by 1px and
       stay clear of the rounded corner(s) along the row */
    & > .tab-list[data-variant="attached"] {
      margin-bottom: -1px;
      margin-inline-end: var(--radius-xl);
      max-width: calc(100% - var(--radius-xl));
    }
    &[data-align="end"] > .tab-list[data-variant="attached"] {
      margin-inline: var(--radius-xl) 0;
    }
    &[data-align="center"] > .tab-list[data-variant="attached"] {
      margin-inline: var(--radius-xl);
      max-width: calc(100% - 2 * var(--radius-xl));
    }

    &[data-side="bottom"] > .tab-list[data-variant="attached"] {
      margin-top: -1px;
      margin-bottom: 0;

      & .tab-trigger {
        border-radius: 0 0 var(--radius-md) var(--radius-md);
        &[aria-selected="true"] { border-bottom-color: var(--border); border-top-color: var(--card); }
      }
    }

    /* left / right (and the legacy column): the gap runs down the column */
    &:is([data-side="left"], [data-side="right"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"])) {
      & > .tab-list[data-variant="attached"] {
        margin-block: 0;
        margin-inline: 0;
        max-width: none;
        grid-auto-flow: row;
        grid-auto-rows: minmax(0, max-content);
        grid-auto-columns: auto;
        padding-bottom: var(--radius-xl);

        & .tab-trigger { width: 100%; }
      }
      &[data-align="end"] > .tab-list[data-variant="attached"] { padding-block: var(--radius-xl) 0; }
      &[data-align="center"] > .tab-list[data-variant="attached"] { padding-block: var(--radius-xl); }
    }
    /* legacy column (a flex row): the card grows to the column's height */
    &:not([data-side]):has(> .tab-list[aria-orientation="vertical"]) {
      & > .tab-list[data-variant="attached"] { max-width: 40%; }
      & > .tab-content:not([hidden]) {
        align-self: stretch;
        display: flex;
        flex-direction: column;

        & > .card { flex: 1; }
      }
    }
    &:is([data-side="left"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"])) > .tab-list[data-variant="attached"] {
      margin-right: -1px;

      & .tab-trigger {
        border-radius: var(--radius-md) 0 0 var(--radius-md);
        &[aria-selected="true"] { border-bottom-color: var(--border); border-right-color: var(--card); }
      }
    }
    &[data-side="right"] > .tab-list[data-variant="attached"] {
      margin-left: -1px;

      & .tab-trigger {
        border-radius: 0 var(--radius-md) var(--radius-md) 0;
        &[aria-selected="true"] { border-bottom-color: var(--border); border-left-color: var(--card); }
      }
    }

    /* the card corner the aligned tabs grow from is square */
    &:not([data-side]):not(:has(> .tab-list[aria-orientation="vertical"])):not([data-align="center"]):not([data-align="end"]) > .tab-content > .card { border-start-start-radius: 0; }
    &:not([data-side]):not(:has(> .tab-list[aria-orientation="vertical"]))[data-align="end"] > .tab-content > .card { border-start-end-radius: 0; }
    &[data-side="top"]:not([data-align="center"]):not([data-align="end"]) > .tab-content > .card { border-start-start-radius: 0; }
    &[data-side="top"][data-align="end"] > .tab-content > .card { border-start-end-radius: 0; }
    &[data-side="bottom"]:not([data-align="center"]):not([data-align="end"]) > .tab-content > .card { border-end-start-radius: 0; }
    &[data-side="bottom"][data-align="end"] > .tab-content > .card { border-end-end-radius: 0; }
    &:is([data-side="left"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"])):not([data-align="center"]):not([data-align="end"]) > .tab-content > .card { border-top-left-radius: 0; }
    &:is([data-side="left"], :not([data-side]):has(> .tab-list[aria-orientation="vertical"]))[data-align="end"] > .tab-content > .card { border-bottom-left-radius: 0; }
    &[data-side="right"]:not([data-align="center"]):not([data-align="end"]) > .tab-content > .card { border-top-right-radius: 0; }
    &[data-side="right"][data-align="end"] > .tab-content > .card { border-bottom-right-radius: 0; }
  }

  /* -- Panel ---------------------------------------------------- */
  .tab-content {
    margin-top: 0.75rem;

    &:focus-visible {
      outline: 2px solid var(--ring);
      outline-offset: 2px;
    }

    &[hidden] { display: none; }
  }

  /* -- Accessibility ------------------------------------------ */

  @media (prefers-reduced-motion: reduce) {
    .tab-trigger { transition: none; }
  }

  @media (forced-colors: active) {
    .tab-trigger[aria-selected="true"] {
      border: 2px solid Highlight;
      box-shadow: none;
    }
    .tab-trigger:disabled { color: GrayText; }

    .tab-list[data-variant="line"] .tab-trigger[aria-selected="true"] {
      border: none;
      border-bottom: 2px solid Highlight;
    }
  }
}
