
/**
 * layouts.css
 *
 * A definitive library of declarative, property-driven layout components.
 * ------------------------------------------------------------------------------
 * This file provides a set of powerful, reusable layout patterns as custom
 * elements that are deeply integrated with the library's design token system.
 *
 * --- PHILOSOPHY ---
 * - Declarative & Semantic: Use `<layout-grid>` instead of `.l-grid`.
 * - Property-Driven: Core logic is controlled by CSS Custom Properties (e.g., `--l-gap`),
 *   which can be overridden by HTML attributes for convenience.
 * - Token-Integrated: Default values are pulled from global design tokens
 *   (e.g., `--space-md`, `--bp-md`) defined in `base.css`.
 * - Composable & Context-Aware: Layouts are designed to be nested and use
 *   container queries to adapt to their local context.
 *
 * This file should be imported into the `components` layer in `index.css`.
 */

/*
 * ==============================================================================
 * DEFAULTS & BASE BEHAVIORS
 * ==============================================================================
 *
 * We use `:where()` to set default variable values with ZERO specificity.
 * This makes them trivial for developers to override at any level.
 */
 :where(layout-grid, [data-layout-grid], .layout-grid, layout-split, [data-layout-split], .layout-split, layout-stack, [data-layout-stack], .layout-stack, layout-cluster, [data-layout-cluster], .layout-cluster, layout-reel, [data-layout-reel], .layout-reel, layout-switcher, [data-layout-switcher], .layout-switcher, layout-pad, [data-layout-pad], .layout-pad, layout-center, [data-layout-center], .layout-center, layout-inline-center, [data-layout-inline-center], .layout-inline-center, layout-frame, [data-layout-frame], .layout-frame, layout-sidebar, [data-layout-sidebar], .layout-sidebar, layout-page, [data-layout-page], .layout-page) {
  /*
   * Default values for layout properties, pulling from global tokens.
   * Assume tokens like `--space-md`, `--bp-md` are defined in `base.css`.
   */
  --l-gap: var(--space-md, 1.5rem);
  --l-breakpoint: var(--bp-sm, 30em);
  --l-padding: var(--space-md, 1.5rem);
  --l-fraction: 1fr;
  --l-justify: flex-start;
  --l-align: stretch;
 }

/* Base styles for all layout components */
:where(layout-grid, [data-layout-grid], .layout-grid, layout-split, [data-layout-split], .layout-split, layout-stack, [data-layout-stack], .layout-stack, layout-cluster, [data-layout-cluster], .layout-cluster, layout-reel, [data-layout-reel], .layout-reel, layout-switcher, [data-layout-switcher], .layout-switcher, layout-pad, [data-layout-pad], .layout-pad, layout-center, [data-layout-center], .layout-center, layout-inline-center, [data-layout-inline-center], .layout-inline-center, layout-frame, [data-layout-frame], .layout-frame, layout-sidebar, [data-layout-sidebar], .layout-sidebar, layout-page, [data-layout-page], .layout-page) {
  display: block;

  /* Prevent children from overflowing their container */
  & > * {
    min-inline-size: 0;
    max-inline-size: 100%;
  }
}

/*
 * Size containment changes intrinsic sizing. Keep it opt-in so a layout used
 * as a flex/grid item sizes from its children unless it actually owns queries.
 */
:where(layout-grid, [data-layout-grid], .layout-grid, layout-split, [data-layout-split], .layout-split, layout-stack, [data-layout-stack], .layout-stack, layout-cluster, [data-layout-cluster], .layout-cluster, layout-reel, [data-layout-reel], .layout-reel, layout-switcher, [data-layout-switcher], .layout-switcher, layout-pad, [data-layout-pad], .layout-pad, layout-center, [data-layout-center], .layout-center, layout-inline-center, [data-layout-inline-center], .layout-inline-center, layout-frame, [data-layout-frame], .layout-frame, layout-sidebar, [data-layout-sidebar], .layout-sidebar, layout-page, [data-layout-page], .layout-page):is([container-query], [data-container-query], .layout-container) {
  container-type: inline-size;
  container-name: var(--layout-container-name, layout-container);
}

/*
 * ==============================================================================
 * GRID-BASED LAYOUTS
 * ==============================================================================
 */

/**
 * <layout-grid>
 * A responsive grid that automatically fits columns.
 * @prop --l-min-item-size: The minimum size for each item.
 * @prop --l-gap: The gap between items.
 * @attr min-item-size, gap
 */
:is(layout-grid, [data-layout-grid], .layout-grid) {
  --_min-item-size: attr(min-item-size type(*), var(--l-min-item-size, 16rem));
  --_gap: attr(gap type(*), var(--l-gap));

  display: grid;
  gap: var(--_gap, var(--l-gap));
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--_min-item-size)), 1fr));
}

/**
 * <layout-split>
 * A two-column layout that splits at a breakpoint.
 * @prop --l-fraction: The ratio for the first column (e.g., "2fr").
 * @prop --l-breakpoint: The container width to split at.
 * @prop --l-gap: The gap between columns.
 * @attr fraction, breakpoint, gap, force-stack, no-stack
 */
:is(layout-split, [data-layout-split], .layout-split) {
  --_fraction: attr(fraction type(*), var(--l-fraction, 1fr));
  --_breakpoint: attr(breakpoint type(*), var(--l-breakpoint));
  --_gap: attr(gap type(*), var(--l-gap));

  display: grid;
  gap: var(--_gap, var(--l-gap));
  grid-template-columns: 1fr; /* Default to stacked */
}
@media (min-width: 30em) {
  :is(layout-split, [data-layout-split], .layout-split):not([force-stack], [data-force-stack], .layout-split-force-stack) {
    grid-template-columns: var(--_fraction, 1fr 1fr);
  }
}
:is(layout-split, [data-layout-split], .layout-split):is([no-stack], [data-no-stack], .layout-split-no-stack) {
  grid-template-columns: var(--_fraction, 1fr 1fr);
}

/*
 * ==============================================================================
 * FLEXBOX-BASED LAYOUTS
 * ==============================================================================
 */

/**
 * <layout-stack>
 * A vertical stack with consistent spacing.
 * @prop --l-gap, --l-align
 * @attr gap, align
 */
:is(layout-stack, [data-layout-stack], .layout-stack) {
  --_gap: attr(gap type(*), var(--l-gap));
  --_align: attr(align type(*), var(--l-align, stretch));

  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: var(--_align, stretch);
  gap: var(--_gap, var(--l-gap));

  /* A stack owns vertical rhythm; child margins would otherwise double it. */
  & > * {
    inline-size: 100%;
    margin-block: 0;
  }

  &[center] {
    align-items: center;
  }

  &[center] > :is(h1, h2, h3, h4, h5, h6, p, small, span, blockquote, pre, a, button, label, summary, details) {
    text-align: center;
  }
}

:is(layout-stack, [data-layout-stack], .layout-stack) > .stack-intrinsic {
  flex-grow: 0;
  inline-size: fit-content;
  max-inline-size: max-content;
  align-self: var(--stack-intrinsic-align, flex-start);
}

:is(layout-stack, [data-layout-stack], .layout-stack)[center] > .stack-intrinsic {
  --stack-intrinsic-align: center;
}

/**
 * <layout-cluster>
 * For grouping items that wrap onto new lines.
 * @prop --l-gap, --l-justify, --l-align
 * @attr gap, justify, align
 */
:is(layout-cluster, [data-layout-cluster], .layout-cluster) {
  --_gap: attr(gap type(*), var(--space-sm, 0.75rem));
  --_justify: attr(justify type(*), var(--l-justify, flex-start));
  --_align: attr(align type(*), var(--l-align, center));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_gap, var(--l-gap));
  justify-content: var(--_justify, flex-start);
  align-items: var(--_align, stretch);
}

/**
 * <layout-reel>
 * A horizontally scrolling container.
 * @prop --l-gap, --scrollbar-thumb, --scrollbar-track
 * @attr gap, no-scrollbar
 */
:is(layout-reel, [data-layout-reel], .layout-reel) {
  --_gap: attr(gap type(*), var(--l-gap));
  --_thumb: var(--scrollbar-thumb, oklch(from var(--theme-primary) l c h / 0.5));
  --_track: var(--scrollbar-track, oklch(from var(--theme-bg) l c h / 0.5));

  display: flex;
  gap: var(--_gap, var(--l-gap));
  overflow-x: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--_thumb) var(--_track);

  & > * { flex-shrink: 0; }
  &[no-scrollbar] { scrollbar-width: none; &::-webkit-scrollbar { display: none; } }
}

/**
 * <layout-switcher>
 * Switches from a stack to a row when items have enough space.
 * @prop --l-threshold, --l-gap
 * @attr threshold, gap
 */
:is(layout-switcher, [data-layout-switcher], .layout-switcher) {
  --_threshold: attr(threshold type(*), var(--l-threshold, 30rem));
  --_gap: attr(gap type(*), var(--l-gap));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_gap, var(--l-gap));

  & > * {
    flex-grow: 1;
    flex-basis: calc((var(--_threshold) - 100%) * 999);
  }
}

/*
 * ==============================================================================
 * WRAPPER & CENTERING LAYOUTS
 * ==============================================================================
 */

/**
 * <layout-pad>
 * Adds consistent padding to its content.
 * @prop --l-padding, --l-padding-inline, --l-padding-block
 * @attr padding, padding-x, padding-y
 */
:is(layout-pad, [data-layout-pad], .layout-pad) {
  --_padding: attr(padding type(*), var(--l-padding));
  --_padding-inline: attr(padding-x type(*), var(--_padding));
  --_padding-block: attr(padding-y type(*), var(--_padding));

  padding-inline: var(--_padding-inline);
  padding-block: var(--_padding-block);
}

/**
 * <layout-center>
 * Centers content horizontally with a max-width for readability.
 * @prop --l-max-width, --l-gutters
 * @attr max-width, gutters, and-text
 */
:is(layout-center, [data-layout-center], .layout-center) {
  --_max-width: attr(max-width type(*), var(--l-max-width, 65ch));
  --_gutters: attr(gutters type(*), var(--l-gutters, var(--space-md, 1.5rem)));

  box-sizing: border-box;
  margin-inline: auto;
  max-width: var(--_max-width);
  padding-inline: var(--_gutters);
  &[and-text] { text-align: center; }
}

/**
 * <layout-inline-center>
 * Centers content horizontally without a max-width constraint.
 * @prop --l-gutters
 * @attr gutters, and-text
 */
:is(layout-inline-center, [data-layout-inline-center], .layout-inline-center) {
  --_gutters: attr(gutters type(*), var(--l-gutters, var(--space-md, 1.5rem)));

  box-sizing: border-box;
  margin-inline: auto;
  padding-inline: var(--_gutters);
  &[and-text] { text-align: center; }
}

/**
 * <layout-frame>
 * Creates a responsive container for media with a fixed aspect ratio.
 * @prop --l-aspect-ratio
 * @attr ratio
 */
:is(layout-frame, [data-layout-frame], .layout-frame) {
  --_ratio: attr(ratio type(*), var(--l-aspect-ratio, 16 / 9));
  position: relative;
  overflow: hidden;
  aspect-ratio: var(--_ratio);

  & > :is(img, video) {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
  }
}

/*
 * ==============================================================================
 * COMPLEX LAYOUT PATTERNS
 * ==============================================================================
 */

/**
 * <layout-sidebar>
 * A sidebar layout that stacks on small containers.
 * @prop --l-breakpoint, --l-side-width, --l-content-min, --l-gap
 * @attr breakpoint, side-width, side, gap
 */
:is(layout-sidebar, [data-layout-sidebar], .layout-sidebar) {
  --_breakpoint: attr(breakpoint type(*), var(--l-breakpoint));
  --_side-width: attr(side-width type(*), var(--l-side-width, 20rem));
  --_content-min: attr(content-min-width type(*), var(--l-content-min, 50%));
  --_gap: attr(gap type(*), var(--l-gap));

  display: flex;
  flex-wrap: wrap;
  gap: var(--_gap, var(--l-gap));

  /* The "switcher" logic for the main content area */
  & > :not(:is([slot="aside"], [data-layout-sidebar-aside], .layout-sidebar__aside)) {
    flex-grow: 9999;
    flex-basis: var(--_content-min);
  }

  /* Sidebar sizing */
  & > :is([slot="aside"], [data-layout-sidebar-aside], .layout-sidebar__aside) {
    flex-grow: 1;
    flex-basis: var(--_side-width);
  }

  /* Handle right-side sidebar using order */
  &[side="right"] > :is([slot="aside"], [data-layout-sidebar-aside], .layout-sidebar__aside) {
    order: 1;
  }
}

/**
 * <layout-page>
 * A standard page layout with header, main content, and footer rows.
 * @prop --l-min-height, --l-gap
 * @attr min-height, gap
 */
:is(layout-page, [data-layout-page], .layout-page) {
  --_min-height: attr(min-height type(*), var(--l-min-height, 100vh));
  --_gap: attr(gap type(*), var(--l-gap, 0));

  display: grid;
  grid-template-rows: auto 1fr auto;
  min-height: var(--_min-height);
  gap: var(--_gap, var(--l-gap));
}
:is(layout-page, [data-layout-page], .layout-page) > [slot="header"] { grid-row: 1; }
:is(layout-page, [data-layout-page], .layout-page) > [slot="main"] { grid-row: 2; }
:is(layout-page, [data-layout-page], .layout-page) > [slot="footer"] { grid-row: 3; }
