
:root {
  --s1: 2px;
  --s2: 4px;
  --s3: 6px;
  --s4: 8px;
  --s5: 10px;
  --s6: 12px;
  --s7: 14px;
  --s8: 16px;
  --s9: 20px;
  --s10: 24px;
  --s11: 32px;
  --s12: 40px;
  --s13: 48px;

  --t1: 9px;
  --t2: 10px;
  --t3: 11px;
  --t4: 12.5px;
  --t5: 13.5px;
  --t6: 15px;
  --t7: 17px;
  --t8: 20px;
  --t9: 24px;
  --t10: 30px;
  --t11: 40px;

  /* Small text is read in bulk and wants air; a heading is one line and a
     loose one reads as two. */
  --lh1: 1.4;
  --lh2: 1.4;
  --lh3: 1.45;
  --lh4: 1.5;
  --lh5: 1.55;
  --lh6: 1.6;
  --lh7: 1.5;
  --lh8: 1.35;
  --lh9: 1.25;
  --lh10: 1.2;
  --lh11: 1.1;

  --r1: 2px;
  --r2: 4px;
  --r3: 6px;
  --r4: 8px;
  --r5: 10px;
  --r6: 12px;
  --r7: 16px;
  --r-pill: 999px;

  /* How long a state takes to arrive. Fifty-three rules across the sheets
     spelled twenty-two different durations for the one thing a hover does,
     and a screen where two neighbours settle at different moments reads as
     two screens. Long enough to be seen, short enough not to be waited for. */
  --quick: .15s ease;

  /* The three measures every product has and each had named for itself —
     `--k-page`/`--k-prose`/`--k-gutter` in the portal, a literal 1240 in nine
     of the portal's rules and in the front page's wrapper, `container` and
     `container-narrow` in the console's. They are *measures* and not steps
     (UI-42), which is why they are lengths here and not rungs; what they are
     not is one product's, so they are named once and a product that wants a
     different page retunes the name rather than inventing one.

     `--measure` and not `--page`: `--page` is the ground a page is painted
     on, and a width called the same thing as a colour is an hour lost the
     first time somebody reaches for the wrong one. */
  --measure: 1240px;
  --prose: 62ch;
  --gutter: clamp(16px, 2.4vw, 44px);
}

/* comm.ee's own look (SITE-8, UIC-17): the ground, the ink, the gold and the
   two faces the front page is set in — kept in Platform so the front page
   and the assistant's door (`ai.<base>`) read one file and agree.

   Three states, not two: the reader's system setting, and the reader
   overruling it either way (`data-theme="light"` / `"dark"` on the root).
   The tier's own pattern in the tier's own order, so nothing needs
   `!important`: the media block is `:root:not([data-theme="light"])` so a
   reader who chose light on a dark machine keeps light, and the explicit
   dark block follows it so a reader who chose dark on a light machine
   gets dark.

   The palette is written onto the *shared* token names as well as its own:
   every `ui-*` control reads --surface, --ink, --line and their kin, so
   setting those from the `--hp-*` values is what makes the controls wear
   this look without a second stylesheet knowing about it (UIC-10: a look
   is modifications on the one set, not a palette of its own). */

:root {
  --hp-bg: #F1F1F0;
  --hp-surface: #FFFFFF;
  --hp-line: #E3E3E1;
  --hp-line2: #CFCFCB;
  --hp-ink: #111111;
  --hp-ink2: #45443F;
  --hp-mute: #6B6A64;
  --hp-on-ink: #F1F1F0;
  --hp-nav: rgba(241, 241, 240, 0.8);
  --hp-link: #7A5B1C;
  --hp-link-hover: #5E4512;
  --hp-gold: #8A6A2A;
  /* How deep a system's tone sinks into the ground for its band: enough to
     tell the bands apart, not enough to stop the page being the ground. */
  --hp-tint: 8%;
  /* The four tones are the same on either ground. */
  --hp-indigo: #5B5BF0;
  --hp-teal: #10C8B4;
  --hp-coral: #FF6B54;
  --hp-amber: #FFB93D;

  /* The faces: a serif with character for the headlines, a plain sans for
     the rest. Loaded by the page's head; these are the names the tier's
     controls set their type in. */
  --sans: 'Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --serif: 'Fraunces', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
}

/* The shared names, at the weight of the tier's own scheme blocks: the
   tier writes its dark under `:root:not([data-theme="light"])`, which
   outweighs a plain `:root` whatever the order, so a mapping written there
   held in light and lost in dark — the assistant's ground came out the
   tier's warm grey on a dark machine, not this black. Every root matches
   one of these two, and both weigh what the tier's blocks weigh. */
:root:not([data-theme="light"]),
:root[data-theme="light"] {
  --bg: var(--hp-bg);
  --page: var(--hp-bg);
  --surface: var(--hp-surface);
  --mid: color-mix(in oklab, var(--hp-bg) 50%, var(--hp-surface));
  --rail: var(--hp-bg);
  --field: var(--hp-surface);
  --hover: color-mix(in oklab, var(--hp-surface) 92%, var(--hp-ink));
  --chip: var(--hp-line);
  --line: var(--hp-line2);
  --line2: var(--hp-line2);
  --hair: var(--hp-line);
  --edge: var(--hp-line2);
  --ring: var(--hp-gold);
  --ink: var(--hp-ink);
  --ink2: var(--hp-ink2);
  --ink3: var(--hp-ink2);
  --mute: var(--hp-mute);
  --faint: var(--hp-mute);
  --rail-ink: var(--hp-mute);
  /* The page's own gold, which is what it spends attention with everywhere
     else — the links, the hover, the mark. */
  --accent: var(--hp-gold);
  --accent-down: var(--hp-link-hover);
  --accent-line: var(--hp-gold);
  --accent-ink: var(--hp-on-ink);
  --accent-deep: var(--hp-link-hover);
  --accent-text: var(--hp-link);
  --chip-ink: var(--hp-link);
  --accent-soft: color-mix(in oklab, var(--hp-gold) 14%, transparent);
  --wash: color-mix(in oklab, var(--hp-gold) 9%, transparent);
  --solid: var(--hp-ink);
  --solid-ink: var(--hp-on-ink);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --hp-bg: #050505;
    --hp-surface: #121212;
    --hp-line: #1E1E1E;
    --hp-line2: #343434;
    --hp-ink: #F3EFE8;
    --hp-ink2: #CFCAC0;
    --hp-mute: #9A958B;
    --hp-on-ink: #050505;
    --hp-nav: rgba(5, 5, 5, 0.72);
    --hp-link: #E2C27A;
    --hp-link-hover: #F1D79A;
    --hp-gold: #D9B36A;
    --hp-tint: 9%;
  }
}
:root[data-theme="dark"] {
  --hp-bg: #050505;
  --hp-surface: #121212;
  --hp-line: #1E1E1E;
  --hp-line2: #343434;
  --hp-ink: #F3EFE8;
  --hp-ink2: #CFCAC0;
  --hp-mute: #9A958B;
  --hp-on-ink: #050505;
  --hp-nav: rgba(5, 5, 5, 0.72);
  --hp-link: #E2C27A;
  --hp-link-hover: #F1D79A;
  --hp-gold: #D9B36A;
  --hp-tint: 9%;
}


:root {
  --m-bar: 72px;
}
@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}
[id] { scroll-margin-top: var(--m-bar); }
body {
  margin: 0; background: var(--page); color: var(--ink);
  font-family: var(--sans); font-size: var(--t7); line-height: var(--lh7);
  -webkit-font-smoothing: antialiased;
}
main { display: block; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; }
.m-wrap { max-width: var(--measure); margin: 0 auto; padding-inline: var(--gutter); }

/* ── the bar across the top ─────────────────────────────────────────────── */
.m-top {
  position: sticky; top: 0; z-index: 10;
  background: color-mix(in oklab, var(--page) 84%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--hair);
}
.m-top-inner { display: flex; align-items: center; gap: var(--s10); height: var(--m-bar); box-sizing: border-box; }
.m-brand { font-family: var(--serif); font-size: var(--t9); font-weight: 500; letter-spacing: -0.01em; }
.m-nav {
  display: flex; gap: var(--s10); margin-left: auto;
  font-size: var(--t5); font-weight: 500; letter-spacing: 0.02em; white-space: nowrap;
}
.m-nav a { color: var(--ink2); }
.m-nav a:hover { color: var(--ink); }
.m-lang { margin-left: auto; font-size: var(--t4); font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mute); white-space: nowrap; }
.m-nav + .m-lang { margin-left: 0; }
.m-lang:hover { color: var(--ink); }

/* ── buttons: pills, thin ───────────────────────────────────────────────── */
.m-btn {
  display: inline-block;
  padding: var(--s6) var(--s10);
  border: 1px solid color-mix(in srgb, var(--ink) 55%, transparent);
  border-radius: var(--r-pill);
  color: var(--ink); font-size: var(--t6); font-weight: 500; letter-spacing: 0.01em;
  transition: transform var(--quick), background var(--quick), color var(--quick), border-color var(--quick);
}
.m-btn:hover { transform: translateY(-1px); border-color: var(--ink); }
.m-btn-primary { background: var(--ink); border-color: var(--ink); color: var(--page); }
.m-btn-primary:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.m-btn-ink { padding: var(--s4) var(--s8); white-space: nowrap; flex: none; }
.m-btn-ink:hover { background: var(--ink); color: var(--page); }
.m-btn-plain { padding: var(--s6) var(--s4); color: var(--ink2); font-size: var(--t6); font-weight: 500; }
.m-btn-plain:hover { color: var(--ink); }

/* ── the hero: the sentence is the picture ──────────────────────────────── */
.m-hero-say {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
  gap: clamp(20px, 3vw, 40px);
  min-height: calc(82svh - var(--m-bar));
  max-width: 980px;
  padding-block: clamp(48px, 6vw, 96px);
}
.m-kicker { margin: 0; font-size: var(--t4); font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--mute); }
.m-h1, .m-h2 {
  margin: 0; font-family: var(--serif); font-optical-sizing: auto; font-weight: 300;
  letter-spacing: -0.02em; text-wrap: balance;
}
.m-h1 { font-size: clamp(40px, 6.4vw, 96px); line-height: 1.02; letter-spacing: -0.025em; }
.m-h2 { font-size: clamp(30px, 4vw, 56px); line-height: var(--lh10); }
.m-lede { margin: 0; max-width: 640px; color: var(--ink2); font-size: clamp(17px, 1.5vw, 21px); text-wrap: pretty; }

/* ── sections ───────────────────────────────────────────────────────────── */
.m-section { padding-block: clamp(64px, 9vw, 128px); border-top: 1px solid var(--hair); }
.m-head { display: flex; flex-direction: column; gap: var(--s6); max-width: 760px; margin-bottom: clamp(32px, 4vw, 56px); }
.m-sub { margin: 0; color: var(--ink2); font-size: var(--t7); text-wrap: pretty; }
.m-albums { display: grid; gap: clamp(40px, 5vw, 72px); }

/* The album is the tier's (UIC-20); what this page adds is the frame every
   picture here wears — a hairline and the small corner — and the shape of
   the box: a render is a wide picture, a plan or a drawing stands on paper. */
.m-album .ui-gal-main { max-height: none; aspect-ratio: 16 / 9; border: 1px solid var(--hair); background: var(--surface); border-radius: var(--r3); }
.m-album.is-plans .ui-gal-main { aspect-ratio: 4 / 3; }
.m-album .ui-gal-thumb { width: 120px; border: 1px solid var(--hair); }

/* ── contact: one column down the middle ────────────────────────────────── */
.m-contact-say { display: flex; flex-direction: column; align-items: center; text-align: center; gap: var(--s8); max-width: 720px; }
.m-reaches { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--s6) var(--s8); margin-top: var(--s6); }

/* ── the foot: `hair-t text-mute` in the markup, the layer's own words ──── */
.m-footer-inner { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--s6) var(--s10); padding-block: var(--s12); font-size: var(--t5); }
.m-footer p { margin: 0; }
.m-footer strong { color: var(--ink); font-weight: 600; }
.m-footer a:hover { color: var(--ink); }

@media (max-width: 980px) {
  .m-nav { display: none; }
  .m-nav + .m-lang { margin-left: auto; }
}
@media (max-width: 620px) {
  .m-top-inner { gap: var(--s6); }
  .m-hero-say { min-height: 0; }
  .m-album .ui-gal-thumb { width: 84px; }
}

/* The utility layer (UI-42). Served after every application's own sheet, so a
   class here wins the tie against a component class setting the same property.

   Every value is a step on `theme/scale.rs` or a token on `theme/tokens.rs`.
   Nothing in this file names a number or a colour of its own. */

/* ── layout ──────────────────────────────────────────────────────────────── */

.flex { display: flex; }
.stack { display: flex; flex-direction: column; }
.row { display: flex; flex-direction: row; align-items: center; }
.grid { display: grid; }
.grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
.grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
.wrap { flex-wrap: wrap; }
.nowrap { flex-wrap: nowrap; }

.start { align-items: flex-start; }
.center { align-items: center; }
.end { align-items: flex-end; }
.baseline { align-items: baseline; }
.stretch { align-items: stretch; }
.between { justify-content: space-between; }
.around { justify-content: space-around; }
.jstart { justify-content: flex-start; }
.jcenter { justify-content: center; }
.jend { justify-content: flex-end; }

/* What one child says about itself, against what its container said about
   all of them. A chip in a column is the usual case: the column stretches
   its children and the chip is as wide as its own word. */
.self-start { align-self: flex-start; }
.self-center { align-self: center; }
.self-end { align-self: flex-end; }

.grow { flex: 1 1 auto; min-width: 0; }
.none { flex: none; }
.shrink { min-width: 0; }

.block { display: block; }
.inline { display: inline; }
.iblock { display: inline-block; }
.iflex { display: inline-flex; align-items: center; }
.relative { position: relative; }
.absolute { position: absolute; }
.fixed { position: fixed; }
.sticky { position: sticky; }
.inset-0 { inset: 0; }
.clip { overflow: hidden; }
.scroll-y { overflow-y: auto; }
.scroll-x { overflow-x: auto; }

/* What a script puts an element behind. The three sheets each carried their
   own copy of this one declaration, so which one a screen got depended on
   which application was serving it. `!important` because it answers a
   `display` the element already has, and it is the only one in the layer. */
.hidden { display: none !important; }

/* A box that fills what holds it is not a measure — it is the absence of one,
   and the same three declarations were written 157 times between the sheets. */
.w-full { width: 100%; }
.h-full { height: 100%; }
.cover { object-fit: cover; }


/* ── space ───────────────────────────────────────────────────────────────── */

.gap-0 { gap: 0; }
.gap-1 { gap: var(--s1); }
.gap-2 { gap: var(--s2); }
.gap-3 { gap: var(--s3); }
.gap-4 { gap: var(--s4); }
.gap-5 { gap: var(--s5); }
.gap-6 { gap: var(--s6); }
.gap-7 { gap: var(--s7); }
.gap-8 { gap: var(--s8); }
.gap-9 { gap: var(--s9); }
.gap-10 { gap: var(--s10); }
.gap-11 { gap: var(--s11); }
.gap-12 { gap: var(--s12); }
.gap-13 { gap: var(--s13); }

.gx-0 { column-gap: 0; }
.gx-1 { column-gap: var(--s1); }
.gx-2 { column-gap: var(--s2); }
.gx-3 { column-gap: var(--s3); }
.gx-4 { column-gap: var(--s4); }
.gx-5 { column-gap: var(--s5); }
.gx-6 { column-gap: var(--s6); }
.gx-7 { column-gap: var(--s7); }
.gx-8 { column-gap: var(--s8); }
.gx-9 { column-gap: var(--s9); }
.gx-10 { column-gap: var(--s10); }
.gx-11 { column-gap: var(--s11); }
.gx-12 { column-gap: var(--s12); }
.gx-13 { column-gap: var(--s13); }

.gy-0 { row-gap: 0; }
.gy-1 { row-gap: var(--s1); }
.gy-2 { row-gap: var(--s2); }
.gy-3 { row-gap: var(--s3); }
.gy-4 { row-gap: var(--s4); }
.gy-5 { row-gap: var(--s5); }
.gy-6 { row-gap: var(--s6); }
.gy-7 { row-gap: var(--s7); }
.gy-8 { row-gap: var(--s8); }
.gy-9 { row-gap: var(--s9); }
.gy-10 { row-gap: var(--s10); }
.gy-11 { row-gap: var(--s11); }
.gy-12 { row-gap: var(--s12); }
.gy-13 { row-gap: var(--s13); }

.p-0 { padding: 0; }
.p-1 { padding: var(--s1); }
.p-2 { padding: var(--s2); }
.p-3 { padding: var(--s3); }
.p-4 { padding: var(--s4); }
.p-5 { padding: var(--s5); }
.p-6 { padding: var(--s6); }
.p-7 { padding: var(--s7); }
.p-8 { padding: var(--s8); }
.p-9 { padding: var(--s9); }
.p-10 { padding: var(--s10); }
.p-11 { padding: var(--s11); }
.p-12 { padding: var(--s12); }
.p-13 { padding: var(--s13); }

.px-0 { padding-inline: 0; }
.px-1 { padding-inline: var(--s1); }
.px-2 { padding-inline: var(--s2); }
.px-3 { padding-inline: var(--s3); }
.px-4 { padding-inline: var(--s4); }
.px-5 { padding-inline: var(--s5); }
.px-6 { padding-inline: var(--s6); }
.px-7 { padding-inline: var(--s7); }
.px-8 { padding-inline: var(--s8); }
.px-9 { padding-inline: var(--s9); }
.px-10 { padding-inline: var(--s10); }
.px-11 { padding-inline: var(--s11); }
.px-12 { padding-inline: var(--s12); }
.px-13 { padding-inline: var(--s13); }

.py-0 { padding-block: 0; }
.py-1 { padding-block: var(--s1); }
.py-2 { padding-block: var(--s2); }
.py-3 { padding-block: var(--s3); }
.py-4 { padding-block: var(--s4); }
.py-5 { padding-block: var(--s5); }
.py-6 { padding-block: var(--s6); }
.py-7 { padding-block: var(--s7); }
.py-8 { padding-block: var(--s8); }
.py-9 { padding-block: var(--s9); }
.py-10 { padding-block: var(--s10); }
.py-11 { padding-block: var(--s11); }
.py-12 { padding-block: var(--s12); }
.py-13 { padding-block: var(--s13); }

.pt-0 { padding-top: 0; }
.pt-1 { padding-top: var(--s1); }
.pt-2 { padding-top: var(--s2); }
.pt-3 { padding-top: var(--s3); }
.pt-4 { padding-top: var(--s4); }
.pt-5 { padding-top: var(--s5); }
.pt-6 { padding-top: var(--s6); }
.pt-7 { padding-top: var(--s7); }
.pt-8 { padding-top: var(--s8); }
.pt-9 { padding-top: var(--s9); }
.pt-10 { padding-top: var(--s10); }
.pt-11 { padding-top: var(--s11); }
.pt-12 { padding-top: var(--s12); }
.pt-13 { padding-top: var(--s13); }

.pb-0 { padding-bottom: 0; }
.pb-1 { padding-bottom: var(--s1); }
.pb-2 { padding-bottom: var(--s2); }
.pb-3 { padding-bottom: var(--s3); }
.pb-4 { padding-bottom: var(--s4); }
.pb-5 { padding-bottom: var(--s5); }
.pb-6 { padding-bottom: var(--s6); }
.pb-7 { padding-bottom: var(--s7); }
.pb-8 { padding-bottom: var(--s8); }
.pb-9 { padding-bottom: var(--s9); }
.pb-10 { padding-bottom: var(--s10); }
.pb-11 { padding-bottom: var(--s11); }
.pb-12 { padding-bottom: var(--s12); }
.pb-13 { padding-bottom: var(--s13); }

/* The only margins there are, and all four are `auto` or nothing. Spacing
   between siblings belongs to the container's gap: a margin that suited one
   parent overlapped the next, which is what this layer exists to stop
   (UI-42). An `auto` is not a length — it is which edge the box is pushed to,
   the one thing a gap cannot say. */
.m-0 { margin: 0; }
.mx-auto { margin-inline: auto; }
.my-auto { margin-block: auto; }
.ml-auto { margin-left: auto; }

/* Where a page stops, and where a reading inside it stops. Every product had
   both and each had named them for itself; the names are the scale's now, so
   a block that lines up with the page says so in the markup.
   **After the margins on purpose**: `m-0 measure` has to mean "no margin of
   its own, and centred", which is what an element wearing both is asking
   for. Written above them it lost the `auto` to the reset, and the foot's
   own hairline was capped at the measure and then left-aligned under bands
   that were centred. */
.measure { width: 100%; max-width: var(--measure); margin-inline: auto; }
.prose { max-width: var(--prose); }
.gutter { padding-inline: var(--gutter); }

/* ── type ────────────────────────────────────────────────────────────────── */

.t-1 { font-size: var(--t1); line-height: var(--lh1); }
.t-2 { font-size: var(--t2); line-height: var(--lh2); }
.t-3 { font-size: var(--t3); line-height: var(--lh3); }
.t-4 { font-size: var(--t4); line-height: var(--lh4); }
.t-5 { font-size: var(--t5); line-height: var(--lh5); }
.t-6 { font-size: var(--t6); line-height: var(--lh6); }
.t-7 { font-size: var(--t7); line-height: var(--lh7); }
.t-8 { font-size: var(--t8); line-height: var(--lh8); }
.t-9 { font-size: var(--t9); line-height: var(--lh9); }
.t-10 { font-size: var(--t10); line-height: var(--lh10); }
.t-11 { font-size: var(--t11); line-height: var(--lh11); }

.serif { font-family: var(--serif); }
.sans { font-family: var(--sans); }
.mono { font-family: var(--mono); }

.fw-4 { font-weight: 400; }
.fw-5 { font-weight: 500; }
.fw-6 { font-weight: 600; }
.fw-7 { font-weight: 700; }

.upper { text-transform: uppercase; }
.track { letter-spacing: 0.08em; }
.tabular { font-variant-numeric: tabular-nums; }
.tleft { text-align: left; }
.tcenter { text-align: center; }
.tright { text-align: right; }
.pretty { text-wrap: pretty; }
.balance { text-wrap: balance; }
.truncate { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* `.nowrap` above is the flex one. These two are the text's: a line that may
   not break, and a word — a key, an address, a token — that may break
   anywhere rather than push its column wider. */
.nobr { white-space: nowrap; }
.anywhere { overflow-wrap: anywhere; }

/* ── ink ─────────────────────────────────────────────────────────────────── */

.text-ink { color: var(--ink); }
.text-ink2 { color: var(--ink2); }
.text-ink3 { color: var(--ink3); }
.text-mute { color: var(--mute); }
.text-faint { color: var(--faint); }
.text-accent { color: var(--accent); }
.text-accent-ink { color: var(--accent-ink); }
.text-solid-ink { color: var(--solid-ink); }
.text-danger { color: var(--danger); }
.text-ok { color: var(--ok-ink); }
.text-warn { color: var(--warn-ink); }
.text-info { color: var(--info); }
.text-star { color: var(--star); }

/* ── ground ──────────────────────────────────────────────────────────────── */

.bg-none { background: none; }
.bg-page { background: var(--page); }
.bg-surface { background: var(--surface); }
.bg-rail { background: var(--rail); }
.bg-mid { background: var(--mid); }
.bg-chip { background: var(--chip); }
.bg-field { background: var(--field); }
.bg-accent { background: var(--accent); }
.bg-accent-soft { background: var(--accent-soft); }
.bg-solid { background: var(--solid); }
.bg-danger-soft { background: var(--danger-soft); }
.bg-ok { background: var(--ok-bg); }
.bg-warn { background: var(--warn-bg); }
.bg-info-soft { background: var(--info-soft); }
.bg-star-soft { background: var(--star-soft); }

/* ── edges ───────────────────────────────────────────────────────────────── */

.line { border: 1px solid var(--line); }
.line-t { border-top: 1px solid var(--line); }
.line-b { border-bottom: 1px solid var(--line); }
.line-l { border-left: 1px solid var(--line); }
.line-r { border-right: 1px solid var(--line); }
.line2 { border: 1px solid var(--line2); }
.hair { border: 1px solid var(--hair); }
.hair-t { border-top: 1px solid var(--hair); }
.hair-b { border-bottom: 1px solid var(--hair); }
.line-accent { border: 1px solid var(--accent-line); }
.line-danger { border: 1px solid var(--danger-line); }
.line-warn { border: 1px solid var(--warn-line); }
.line-none { border: 0; }

.r-0 { border-radius: 0; }
.r-1 { border-radius: var(--r1); }
.r-2 { border-radius: var(--r2); }
.r-3 { border-radius: var(--r3); }
.r-4 { border-radius: var(--r4); }
.r-5 { border-radius: var(--r5); }
.r-6 { border-radius: var(--r6); }
.r-7 { border-radius: var(--r7); }
.r-pill { border-radius: var(--r-pill); }

.shadow { box-shadow: var(--shadow); }
.shadow-pop { box-shadow: var(--pop); }
.shadow-none { box-shadow: none; }

/* ── what answers a pointer ──────────────────────────────────────────────── */

/* The sheets spelled twenty-two different transitions between them, and
   fifty-three rules wanted the same one: the colours move, nothing else, and
   the eye reads the change as a state rather than as an animation. */
.transition-colors { transition: background var(--quick), border-color var(--quick), color var(--quick); }
.transition-transform { transition: transform var(--quick); }

.cursor-pointer { cursor: pointer; }
.cursor-default { cursor: default; }
.pointer-none { pointer-events: none; }
.pointer-auto { pointer-events: auto; }

.hover-text-ink:hover { color: var(--ink); }
.hover-text-accent:hover { color: var(--accent); }
.hover-text-danger:hover { color: var(--danger); }
.hover-underline:hover { text-decoration: underline; text-underline-offset: 2px; }

.hover-bg-hover:hover { background: var(--hover); }
.hover-bg-chip:hover { background: var(--chip); }
.hover-bg-surface:hover { background: var(--surface); }
.hover-bg-accent-soft:hover { background: var(--accent-soft); }

.hover-line-accent:hover { border-color: var(--accent); }
.hover-line-ink:hover { border-color: var(--ink); }
.hover-line-danger:hover { border-color: var(--danger); }

.active-bg-down:active { background: var(--accent-down); }

/* A ring the keyboard draws and the mouse does not, taking the corner of
   whatever it is put on rather than deciding one of its own. */
.focus-ring:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: inherit; }
.focus-none:focus { outline: none; }

/* Not `[disabled]`: a link and a label can be past answering too, and neither
   takes the attribute. */
.disabled { opacity: 0.5; cursor: default; pointer-events: none; }

/* ── the desk (UIC-23) ───────────────────────────────────────────────────── */

/* Mobile is the ground. A utility above is every width, and its `d-` twin
   is the desk — 641px and up, measured on the page's own width (the body is
   the container, `layouts.css`), so a page narrowed by the dock is a phone
   to it. `row d-stack` is a row on a phone and a column on a desk; the twin
   comes after the base in this file, which is what lets it win the tie.
   Only the arrangement has twins: what changes between a phone and a desk
   is where things stand, not what colour they are. */
@container (min-width: 641px) {
  .d-flex { display: flex; }
  .d-stack { display: flex; flex-direction: column; }
  .d-row { display: flex; flex-direction: row; align-items: center; }
  .d-grid { display: grid; }
  .d-grid-2 { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .d-grid-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .d-grid-4 { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .d-block { display: block; }
  .d-iflex { display: inline-flex; align-items: center; }
  .d-hidden { display: none; }
  .d-wrap { flex-wrap: wrap; }
  .d-nowrap { flex-wrap: nowrap; }

  .d-start { align-items: flex-start; }
  .d-center { align-items: center; }
  .d-end { align-items: flex-end; }
  .d-stretch { align-items: stretch; }
  .d-between { justify-content: space-between; }
  .d-jstart { justify-content: flex-start; }
  .d-jcenter { justify-content: center; }
  .d-jend { justify-content: flex-end; }

  .d-grow { flex: 1 1 auto; min-width: 0; }
  .d-none { flex: none; }
  .d-w-full { width: 100%; }

  .d-gap-0 { gap: 0; }
  .d-gap-1 { gap: var(--s1); }
  .d-gap-2 { gap: var(--s2); }
  .d-gap-3 { gap: var(--s3); }
  .d-gap-4 { gap: var(--s4); }
  .d-gap-5 { gap: var(--s5); }
  .d-gap-6 { gap: var(--s6); }
  .d-gap-7 { gap: var(--s7); }
  .d-gap-8 { gap: var(--s8); }
  .d-gap-9 { gap: var(--s9); }
  .d-gap-10 { gap: var(--s10); }
  .d-gap-11 { gap: var(--s11); }
  .d-gap-12 { gap: var(--s12); }
  .d-gap-13 { gap: var(--s13); }
}
