@layer base {
/*
@elements/ui: base (inside @layer base)

Default styling for bare HTML elements. No :where() needed for SPECIFICITY
: the cascade layer puts these BELOW components and utilities, so any class
or utility wins automatically.

THAT ARGUMENT DOES NOT COVER INHERITANCE, and the difference is the reason
these rules set almost no colors. A declaration that MATCHES an element
beats an INHERITED value at any specificity, in any layer, and :where()
does not change that: inheritance is only consulted when nothing matches.
So `h2 { color: var(--ink) }` is not a harmless restatement of the default:
it is the thing that makes a heading go invisible the moment someone writes
a dark panel, a callout or an inverted hero that sets `color:`.

RULE FOR THIS FILE: set `color` on a bare element only when the element
also owns its `background` (code, pre, kbd, mark, ::selection). Those own
both sides of the pairing and must not float with the surroundings.
Everything else either inherits, or uses --ink-soft-flow, which is derived
from currentColor so it stays soft AND inherits. See the token comment in
themes/default.css.

SPACING. The reset zeroes every margin so components can lay themselves out
with gap. This file puts flow spacing back for ordinary document markup, so
a page written with no classes at all reads correctly. The layout primitives
(.stack, .cluster, .row) sit in a later layer and zero their children's
margins again, so a gap-based layout never doubles up.

Native widgets (progress, meter, details) live in native.css.
*/

/* No page frame here. This file styles elements: type, color, spacing
   rhythm, links, lists, tables, code. It sets no width, no centering and no
   padding on a container, and it never reaches into a descendant. A class
   only ever adds behavior; nothing keys on a class being absent, so styling
   a footer cannot move the page.

   Width is a layout decision and lives in layout.css, where it is named and
   visible in the markup: .page-shell, and .is-prose for an article measure.
   `elements create page` writes it for you. */

html {
  font-family:    var(--font-sans);
  line-height:    var(--leading-body);
  color:          var(--ink);
  background:     var(--bg);
}

body {
  font-family:    var(--font-sans);
  font-size:      var(--text-base);
  line-height:    var(--leading-body);
  color:          var(--ink);
  background:     var(--bg);
}

/* FOCUS: the reset kills the UA outline so components can draw their own
   ring. This is the floor underneath that: anything focusable with no ring of
   its own still gets one. Without it a custom widget, or any element carrying
   tabindex, is focusable with no visible indicator, which is the kind of defect
   a beginner ships without knowing.

   :where() keeps it at zero specificity and it is declared FIRST, so both the
   link ring below and every component ring in a later layer replace it rather
   than stacking a second outline on top. */
:where(:focus-visible) {
  outline:        2px solid var(--focus);
  outline-offset: 2px;
}

/* HEADINGS: generous, modern scale */

h1 {
  font-size:      var(--text-4xl);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

h2 {
  font-size:      var(--text-3xl);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

h3 {
  font-size:      var(--text-2xl);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-tight);
  letter-spacing: var(--tracking-snug);
}

h4 {
  font-size:      var(--text-xl);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-snug);
}

h5 {
  font-size:      var(--text-lg);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-snug);
}

h6 {
  font-size:      var(--text-base);
  font-weight:    var(--weight-semibold);
  line-height:    var(--leading-snug);
}

/* PARAGRAPH */
p { line-height: var(--leading-body); }

/*
FLOW

The reset zeroes every margin so components can space themselves with gap.
Document content still needs vertical rhythm, and this is where it comes
back. One rule per ROLE, not one per element:

  a block of running content opens --space-4 above and below it
  a heading opens a larger lead, so sections separate more strongly than
    the paragraphs inside one do, and closes tighter to the content it
    introduces, because a heading belongs to what follows it

Margins collapse between siblings, so a heading's lead and the preceding
paragraph's space resolve to the larger of the two instead of stacking.
Element margins rather than an owl (`* + *`) on purpose: a paragraph
followed by a plain <div> is still spaced, and a component's own children
are left alone. .prose uses the owl over the top of this for the tighter
editorial rhythm; see typography.css.

Line length is not capped here. A measure is a property of the container
that wants one, not of every paragraph on the page. .page-shell.is-prose is
65ch wide, so the text inside it is measured by the box, and a centered
paragraph in a hero stays centered under its heading.
*/

p, ul, ol, dl, blockquote, pre, table, figure, form, details {
  margin-block: var(--space-4);
}

h1, h2     { margin-block: var(--space-10) var(--space-4); }
h3         { margin-block: var(--space-8)  var(--space-3); }
h4, h5, h6 { margin-block: var(--space-6)  var(--space-2); }

hr { margin-block: var(--space-8); }

/* Clear the outer edges. A padded container (a .card, a .callout, the page
   frame) must not gain a phantom band of space inside its own padding, and
   the reader must not gain one at the top of the page. */
:is(h1, h2, h3, h4, h5, h6, p, ul, ol, dl,
    blockquote, pre, table, figure, form, details, hr):first-child {
  margin-block-start: 0;
}

:is(h1, h2, h3, h4, h5, h6, p, ul, ol, dl,
    blockquote, pre, table, figure, form, details, hr):last-child {
  margin-block-end: 0;
}

/* LINKS: wrapped in :where() so component classes (.button, .link-action,
   etc.) can override without specificity battles inside the same layer too.

   A bare <a> takes --link, the theme's link color: the accent in a branded
   theme, the ink in a monochrome one. An app rebrands links by setting
   --accent, or --link itself.

   Without --link (the base stylesheet on its own) the fallback takes the
   lightness from the text around the link, nudged 20% further from mid-grey,
   and the chroma and hue from --link-c and --link-h, or from that text when
   they are unset. The chroma is capped to what sRGB holds at that lightness:
   min(0.16 * L, 0.45 * (1 - L)) is in gamut for every hue. */
:where(a) {
  color:                  var(--link, oklch(from currentColor
                                calc(l + (l - 0.5) * 0.2)
                                max(0, min(var(--link-c, c),
                                           calc((l + (l - 0.5) * 0.2) * 0.16),
                                           calc((1 - (l + (l - 0.5) * 0.2)) * 0.45)))
                                var(--link-h, h)));
  text-decoration:        underline;
  text-decoration-color:  color-mix(in oklab, currentColor 30%, transparent);
  text-underline-offset:  0.25em;
  transition:             var(--transition-colors);
}
:where(a:hover) { text-decoration-color: currentColor; }
:where(a:focus-visible) {
  outline:        none;
  box-shadow:     var(--focus-ring);
  border-radius:  var(--radius-xs);
}

/* LISTS: the reset strips markers so a nav or a menu built from <ul> starts
   clean. A bare list is not a nav, it is a list, so the markers come back here.
   The layout primitives strip them again for the nav case. */
ul { list-style: disc; }
ol { list-style: decimal; }
ul, ol { padding-inline-start: var(--space-6); }

/* No space between items and no indent on dd here, so a list an app lays
   out as a row or a grid (breadcrumbs, a card grid, a stat row) lines up
   with nothing to undo. The editorial rhythm lives on .prose
   (typography.css), where long-form text asks for it. */
li { line-height: var(--leading-body); }

li > ul, li > ol { margin-block: var(--space-1); }
ul ul { list-style: circle; }
ul ul ul { list-style: square; }
dt { font-weight: var(--weight-semibold); }
dd {
  margin-block-end: var(--space-3);
  color:            var(--ink-soft-flow);
}
dd:last-child { margin-block-end: 0; }

/* QUOTE / HR */
blockquote {
  padding-left: var(--space-4);
  border-left:  3px solid var(--rule);
  color:        var(--ink-soft-flow);
  font-style:   italic;
}
hr {
  border: none;
  border-top: 1px solid var(--rule);
}

/* CODE */
code {
  font-family:   var(--font-mono);
  font-size:     0.92em;
  background:    var(--bg-muted);
  color:         var(--ink);
  padding:       0.15em 0.4em;
  border-radius: var(--radius-xs);
}
pre {
  font-family:   var(--font-mono);
  font-size:     var(--text-sm);
  line-height:   var(--leading-snug);
  background:    var(--bg-inverse);
  color:         var(--ink-inverse);
  padding:       var(--space-4);
  border-radius: var(--radius-surface);
  overflow-x:    auto;
  tab-size:      2;
}
pre code {
  background:    transparent;
  padding:       0;
  font-size:     inherit;
  color:         inherit;
  border-radius: 0;
}

/* KBD */
kbd {
  display:       inline-block;
  font-family:   var(--font-mono);
  font-size:     0.85em;
  background:    var(--bg-muted);
  color:         var(--ink);
  padding:       0.15em 0.45em;
  border:        1px solid var(--rule);
  border-radius: var(--radius-xs);
  box-shadow:    0 1px 0 var(--rule);
}

/* MARK */
mark {
  background:    var(--warning-soft);
  color:         var(--warning-ink);
  padding:       0 0.1em;
  border-radius: var(--radius-xs);
}

/* TABLES */
table {
  width:           100%;
  font-size:       var(--text-sm);
  line-height:     var(--leading-snug);
  border-collapse: collapse;
}
thead { border-bottom: 1px solid var(--rule); }
tbody tr + tr { border-top: 1px solid var(--rule-soft); }
th {
  text-align:  left;
  font-weight: var(--weight-semibold);
  color:       var(--ink-soft-flow);
  padding:     var(--space-2) var(--space-3);
}
td {
  padding:        var(--space-2) var(--space-3);
  vertical-align: top;
}

figcaption {
  font-size:  var(--text-sm);
  color:      var(--ink-soft-flow);
  margin-top: var(--space-2);
}

/* FORMS: a bare form is a stack of labels and controls with no wrapper, so
   the spacing has to come from the form itself. A label sits close to the
   control it names; separate fields get a full gap.

   The spacing is a grid gap, not a margin, so it applies only while the form
   owns its layout. An author who writes `display: flex` and a gap to put an
   input beside its button replaces that layout wholesale, and nothing is
   left pushing the controls out of line. */

form {
  display:       grid;
  gap:           var(--space-4);
  align-content: start;
}

/* Grid stretches its items, which is right for a control and wrong for a
   button: a bare Save should be its own width, as it is anywhere else. */
form > :is(button, .button,
           input[type="submit"], input[type="reset"], input[type="button"]) {
  justify-self: start;
}

label { display: block; }
label:has(> input[type="checkbox"]),
label:has(> input[type="radio"]) {
  display:     flex;
  align-items: center;
  gap:         var(--space-2);
}

/* A label and its control are one thing, so they sit a tight step apart rather
   than a full one. Directly inside a form the grid gap is already between
   them, and this pulls back to the tighter step; anywhere else (inside .field,
   say) there is no gap and the step is added outright. */
form > label + :is(input, textarea, select) {
  margin-block-start: calc(var(--space-1) - var(--space-4));
}

label + input, label + textarea, label + select { margin-block-start: var(--space-1); }

::selection {
  background: color-mix(in oklab, var(--accent) 22%, transparent);
  color:      var(--ink);
}

}
