/* -- 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; }
  }
}
