//! `oriel-core` — the headless core of the **oriel** data grid.
//!
//! Pure logic, zero dependencies: virtualization math and interaction/view
//! state, plus the *definitions* of the two seams an integrator satisfies.
//! It imports no GUI crate and knows nothing about how or where rows render.
//! If you are building an application, you almost certainly want a renderer
//! integration crate instead — [`oriel-iced`] is the shipped one, and its
//! crate docs carry the runnable quickstart. This crate is where the
//! *concepts* live:
//!
//! - [`data`] — **the data seam.** Your row store implements
//!   [`DataSource`](data::DataSource): an async, index-ranged `fetch`, a
//!   tolerant row count, and an opaque, stable `RowId` per row. The grid
//!   never copies your dataset; it asks for the visible slice.
//!   [`VecStore`](data::VecStore) is the batteries-included resident store
//!   (and a public example — it uses no privileged internals).
//! - [`columns`] — **the render seam.** Each column implements
//!   [`Column`](columns::Column), producing per-cell values of an *opaque*
//!   `Element` type the core never inspects. Sizing policy and the
//!   shareable [`ColumnLayout`](columns::ColumnLayout) live here too.
//! - [`query`] — **sort/filter specs** as plain representable data
//!   ([`QuerySpec`](query::QuerySpec)): the view owns the spec, the store
//!   executes it (in memory, or pushed down to a real query engine).
//! - [`selection`] — selection as a **set of `RowId`s**, identity-keyed so
//!   it survives re-sorting and mutation by construction.
//! - [`viewport`] — the virtualization math
//!   ([`RowVirtualizer`](viewport::RowVirtualizer)): materialized rows are
//!   a function of the viewport, never of the total row count, and the
//!   scroll position of truth is a row-space
//!   [`ScrollAnchor`](viewport::ScrollAnchor).
//!
//! # Why the split
//!
//! The dependency points one way — integration crates depend on this one,
//! never the reverse — so everything here is unit-testable with no GUI in
//! the loop, and a second renderer integration reuses all of it. The seams
//! are *traits the integrator satisfies*; the core deliberately has **no**
//! render/backend abstraction of its own.
//!
//! The opacity is real, not aspirational — a `Column` whose element type is
//! `String` is a perfectly valid (if unusual) implementation, which is also
//! how the core stays testable headlessly:
//!
//! ```
//! use oriel_core::columns::{Column, ColumnId, ColumnSizing};
//!
//! struct NameColumn;
//!
//! impl Column for NameColumn {
//!     type Row = (u64, String);
//!     type Element = String; // the core never looks inside
//!
//!     fn id(&self) -> ColumnId {
//!         ColumnId(1)
//!     }
//!     fn sizing(&self) -> ColumnSizing {
//!         ColumnSizing::resizable(200.0)
//!     }
//!     fn header(&self) -> String {
//!         "Name".into()
//!     }
//!     fn cell(&self, row: &(u64, String)) -> String {
//!         row.1.clone()
//!     }
//! }
//! ```
//!
//! # Feature flags
//!
//! - `serde` *(off by default)* — `Serialize`/`Deserialize` on the spec and
//!   layout state types ([`QuerySpec`](query::QuerySpec),
//!   [`ColumnId`](columns::ColumnId), …) for presets and persistence. The
//!   default build has **zero** dependencies.
//!
//! [`oriel-iced`]: https://docs.rs/oriel-iced

// Machinery, not habit: the public surface is documented
// to docs.rs standard — keep it that way by construction.
#![deny(missing_docs)]
#![deny(rustdoc::broken_intra_doc_links)]

pub mod columns;
pub mod data;
pub mod query;
pub mod selection;
pub mod viewport;
