/* -- Border Layout component --------------------------------------
   An application frame in five regions - north, south, west, east around a
   center - on a CSS grid. Every side region that should resize is a
   .resizer wrapping its pane: inside a border layout the resizer's handle
   becomes a full-length divider (line, optional grip), dragged or moved with
   the arrow keys. Regions left out collapse, so the same frame is a
   horizontal split, a vertical split, three columns... */

@layer components {
  .border-layout {
    /* the divider, themable per layout or per region */
    --_line-width: var(--border-layout-divider-width, 1px);
    --_line-style: solid;
    --_line-color: var(--border-layout-divider-color, var(--border));
    --_accent: var(--border-layout-accent, var(--ring));
    --_hit: 0.75rem;
    --_gap: 0px;

    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: auto minmax(0, 1fr) auto;
    /* north and south dominate: they span the full width */
    grid-template-areas:
      "north north north"
      "west  center east"
      "south south south";
    gap: var(--_gap);
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    background: var(--card);
    color: var(--card-foreground);

    /* west and east dominate: they span the full height */
    &[data-dominant="we"] {
      grid-template-areas:
        "west north  east"
        "west center east"
        "west south  east";
    }

    /* no frame of its own - fills a window or a page */
    &[data-frame="none"] {
      border: 0;
      border-radius: 0;
      background: transparent;
    }
  }

  .border-layout > .border-layout-north {
    grid-area: north;
  }
  .border-layout > .border-layout-south {
    grid-area: south;
  }
  .border-layout > .border-layout-west {
    grid-area: west;
  }
  .border-layout > .border-layout-east {
    grid-area: east;
  }
  .border-layout > .border-layout-center {
    grid-area: center;
    min-width: 0;
    min-height: 0;
    overflow: auto;
  }

  /* -- Regions ------------------------------------------------------ */
  /* a resizable region: the resizer wrapper fills its grid cell, its pane
     stretches across the other axis and carries the size on its own */
  .border-layout > .resizer {
    display: flex;
    width: auto;
    min-width: 0;
    min-height: 0;
  }
  .border-layout > :is(.border-layout-north, .border-layout-south).resizer {
    flex-direction: column;
  }
  .border-layout > .resizer > :not(.resizer-handle) {
    flex: none;
    box-sizing: border-box;
    min-width: 0;
    min-height: 0;
    overflow: auto;
  }
  /* the pane of a collapsed region is gone; its divider stays to bring it back */
  .border-layout > .resizer[data-collapsed] > :not(.resizer-handle) {
    display: none;
  }

  /* a region that does not resize still gets the divider line */
  .border-layout > .border-layout-north:not(.resizer) {
    border-block-end: var(--_line-width) var(--_line-style) var(--_line-color);
  }
  .border-layout > .border-layout-south:not(.resizer) {
    border-block-start: var(--_line-width) var(--_line-style) var(--_line-color);
  }
  .border-layout > .border-layout-west:not(.resizer) {
    border-inline-end: var(--_line-width) var(--_line-style) var(--_line-color);
  }
  .border-layout > .border-layout-east:not(.resizer) {
    border-inline-start: var(--_line-width) var(--_line-style) var(--_line-color);
  }

  /* padding for panes that hold text (optional) */
  .border-layout-pane {
    padding: 0.75rem;
  }

  /* -- Dividers: the resizer handle, redrawn --------------------------- */
  .border-layout > .resizer > .resizer-handle {
    z-index: 5;
    width: auto;
    height: auto;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
    opacity: 1;
    color: var(--muted-foreground);

    /* the line */
    &::before {
      content: "";
      position: absolute;
      transition: border-color 120ms;
    }
    /* the grip - hidden unless data-grip asks for one */
    &::after {
      content: none;
      inset: auto;
    }

    &:hover,
    &:focus-visible {
      background: transparent;
      outline: none;
    }
    &:is(:hover, :focus-visible)::before {
      border-color: var(--_accent);
    }
    &:focus-visible::after {
      outline: 2px solid var(--_accent);
      outline-offset: 1px;
    }

    /* vertical dividers: west's east edge, east's west edge */
    &:is([data-handle="e"], [data-handle="w"]) {
      top: 0;
      bottom: 0;
      width: var(--_hit);
      cursor: col-resize;
      &::before {
        inset-block: 0;
        left: 50%;
        border-inline-start: var(--_line-width) var(--_line-style) var(--_line-color);
        translate: -50% 0;
      }
    }
    &[data-handle="e"] {
      right: 0;
      left: auto;
      translate: calc(50% + var(--_gap) / 2) 0;
    }
    &[data-handle="w"] {
      left: 0;
      right: auto;
      translate: calc(-50% - var(--_gap) / 2) 0;
    }

    /* horizontal dividers: north's south edge, south's north edge */
    &:is([data-handle="n"], [data-handle="s"]) {
      left: 0;
      right: 0;
      height: var(--_hit);
      cursor: row-resize;
      &::before {
        inset-inline: 0;
        top: 50%;
        border-block-start: var(--_line-width) var(--_line-style) var(--_line-color);
        translate: 0 -50%;
      }
    }
    &[data-handle="s"] {
      bottom: 0;
      top: auto;
      translate: 0 calc(50% + var(--_gap) / 2);
    }
    &[data-handle="n"] {
      top: 0;
      bottom: auto;
      translate: 0 calc(-50% - var(--_gap) / 2);
    }
  }

  /* dragging: the divider lights up; the resizer's own box outline stays off */
  .border-layout > .resizer[data-resizing] {
    outline: none;
    & > .resizer-handle {
      background: transparent;
    }
    & > .resizer-handle::before {
      border-color: var(--_accent);
    }
  }

  /* -- Grips: data-grip on the layout (every divider) or on one region -- */
  :is(.border-layout[data-grip] > .resizer, .border-layout > .resizer[data-grip]) > .resizer-handle::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    translate: -50% -50%;
    box-sizing: border-box;
    border-radius: var(--radius-sm);
  }
  /* dots: a small card with a dotted grip */
  :is(.border-layout[data-grip="dots"] > .resizer, .border-layout > .resizer[data-grip="dots"])
    > .resizer-handle::after {
    width: 0.75rem;
    height: 1.25rem;
    border: 1px solid var(--_line-color);
    background:
      radial-gradient(circle, currentColor 0.75px, transparent 1.25px) center / 4px 4px,
      var(--background);
  }
  /* bar: a pill across the line */
  :is(.border-layout[data-grip="bar"] > .resizer, .border-layout > .resizer[data-grip="bar"]) > .resizer-handle::after {
    width: 0.25rem;
    height: 2rem;
    border-radius: 999px;
    background: color-mix(in oklch, var(--foreground) 35%, var(--_line-color));
  }
  /* data-grip="none" - on the layout (regions without their own grip) or one
     region - switches it off; more specific than the rules above */
  :is(.border-layout[data-grip="none"] > .resizer:not([data-grip]), .border-layout > .resizer[data-grip="none"])
    > .resizer-handle::after {
    content: none;
  }
  /* horizontal dividers turn the grip sideways */
  .border-layout .resizer > .resizer-handle:is([data-handle="n"], [data-handle="s"])::after {
    rotate: 90deg;
  }
  .border-layout .resizer > .resizer-handle:is(:hover, :focus-visible)::after {
    border-color: var(--_accent);
  }

  /* -- Divider styles (data-divider on the layout or one region) ----------- */
  :is(.border-layout, .border-layout > .resizer, .border-layout > [class*="border-layout-"]) {
    &[data-divider="dashed"] {
      --_line-style: dashed;
    }
    &[data-divider="dotted"] {
      --_line-style: dotted;
      --_line-width: var(--border-layout-divider-width, 2px);
    }
    &[data-divider="double"] {
      --_line-style: double;
      --_line-width: var(--border-layout-divider-width, 4px);
    }
    &[data-divider="thick"] {
      --_line-width: var(--border-layout-divider-width, 4px);
      --_line-color: var(--border-layout-divider-color, var(--muted));
    }
    &[data-divider="none"] {
      --_line-width: 0px;
    }
  }
  /* gap: the regions float as cards in a gutter, the divider lives in the gutter */
  .border-layout[data-divider="gap"] {
    --_gap: 0.5rem;
    --_line-width: 0px;
    padding: var(--_gap);
    background: var(--muted);

    &
      > :is(
        .border-layout-north,
        .border-layout-south,
        .border-layout-west,
        .border-layout-east,
        .border-layout-center
      ):not(.resizer),
    & > .resizer > :not(.resizer-handle) {
      border: 1px solid var(--border);
      border-radius: var(--radius-md);
      background: var(--card);
    }
  }

  /* -- Accessibility -------------------------------------------- */
  @media (prefers-reduced-motion: reduce) {
    .border-layout > .resizer > .resizer-handle::before {
      transition: none;
    }
  }

  @media (prefers-contrast: more) {
    .border-layout {
      --_line-color: var(--foreground);
    }
  }

  @media (forced-colors: active) {
    .border-layout {
      border: 1px solid CanvasText;
      --_line-color: CanvasText;
      --_accent: Highlight;
    }
    .border-layout > .resizer > .resizer-handle::before {
      forced-color-adjust: none;
    }
  }
}
