Port the bundle's borderless component redesign into core
Button, IconButton, Badge, Tag, and Card all currently have a border in
this repo; the Claude Design export of Gloss redesigned all of them
borderless (mono "stamp" buttons, a dot-style Badge, a Card that reads by
surface contrast instead of an outline). Badge and Tag didn't conflict with
anything written down, so they're a straight port. Button, IconButton, and
Card did: elevation.md, card.md, button.md, and icon-button.md all stated
"hairline borders do the elevation work" / "bordered" as an explicit system
rule, in four places, not an accidental gap — so going borderless there
means rewriting the rule itself, not just the CSS. Confirmed with the repo
owner before doing it.

Rewrote elevation.md's core rule (surface contrast, not a border, marks a
bounded surface's edge — hairlines still divide rows/tables/tabs, they just
no longer wrap a whole surface), plus the matching language in card.md,
button.md, icon-button.md, rationale.md's contrast-contract aside, and
color.md's border-contrast callout, so the docs state one consistent story
instead of contradicting the new CSS.

Along the way, found and fixed a real regression the border was masking:
.example (the docs demo box) and .card share the exact same background
token, so several component demos (Card's own "content tile" and "list"
examples, all three CardRow demos, Space's density comparison) went
invisible once the border stopped drawing the boundary. Added
data-surface="sunken" to those demo wrappers, matching the pattern
elevation.md's own demo already used.

Verified in a local build + Playwright screenshots (light and dark) across
Button, IconButton, Badge, Tag, Card, CardRow, Elevation, Space, and the
Archive pattern page.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CUag8hbfEiMpyQ9gxxSzv5
change
commit 8f3f86494a910265e4a3b81ae90f0656a35fd11c
author Claude <noreply@anthropic.com>
date
parent 3423f334
diff --git a/_components/button.md b/_components/button.md
index 3aa74da..59bdcb7 100644
--- a/_components/button.md
+++ b/_components/button.md
@@ -1,17 +1,19 @@
 ---
 title: Button
 summary: >-
-  A flat, quiet button that recedes rather than performs — no gradients, no
-  shine. Five variants, three sizes, one geometry.
+  No border, no ornament — hierarchy is ink density, not an outline. Five
+  variants, three sizes, one geometry.
 ---
 
 ## Variants
 
-`default` is bordered and neutral. `primary` is the accent fill — one
-committing action per view, at most. `dark` is reserved for the single most
-committing action in a screen, typically a final Save; it should be rare.
-`ghost` has no border or fill, for dismissals and tertiary actions. `danger`
-is destructive and irreversible only.
+`default` is quiet — no fill at rest, a flat tint of the stock on hover, the
+same gesture as a CardRow. `primary` is the accent fill — one committing
+action per view, at most. `dark` is reserved for the single most committing
+action in a screen, typically a final Save; it should be rare. `ghost` is
+the same quiet block one step further back — text-secondary instead of
+text-primary — for dismissals and tertiary actions. `danger` is destructive
+and irreversible only.
 
 <figure class="example">
 <figcaption>Variants</figcaption>
@@ -159,11 +161,11 @@ class Button needs, and only anchors reach for it.
   <thead><tr><th scope="col">Element / attribute</th><th scope="col">Values</th><th scope="col">Notes</th></tr></thead>
   <tbody>
     <tr><td><code>button</code></td><td></td><td>Required base. A bare <code>&lt;button&gt;</code> is styled directly — no class. Use <code>&lt;a class="btn"&gt;</code> instead when the control navigates.</td></tr>
-    <tr><td><code>data-variant</code></td><td><code>primary | dark | ghost | danger</code></td><td>Omit for the default, bordered look.</td></tr>
+    <tr><td><code>data-variant</code></td><td><code>primary | dark | ghost | danger</code></td><td>Omit for the default, quiet look — no fill at rest.</td></tr>
     <tr><td><code>data-size</code></td><td><code>sm | lg</code></td><td>Omit for the default (medium) size. Padding only.</td></tr>
     <tr><td><code>data-block</code></td><td>boolean</td><td>Full width of its container.</td></tr>
     <tr><td><code>disabled</code></td><td>boolean</td><td>Removes the button from the tab order.</td></tr>
     <tr><td><code>aria-disabled</code></td><td><code>"true"</code></td><td>Looks disabled, stays focusable.</td></tr>
-    <tr><td><code>[role="group"]</code></td><td></td><td>Wrap adjacent buttons in a group to join their borders and radii.</td></tr>
+    <tr><td><code>[role="group"]</code></td><td></td><td>Wrap adjacent buttons in a group to join their radii; a hairline divider separates them, since the buttons themselves carry no border.</td></tr>
   </tbody>
 </table>
diff --git a/_components/card-row.md b/_components/card-row.md
index a4a461c..e4bfe7d 100644
--- a/_components/card-row.md
+++ b/_components/card-row.md
@@ -13,7 +13,7 @@ class of CardRow's own.
 
 <figure class="example">
 <figcaption>Rows</figcaption>
-<div>
+<div data-surface="sunken">
 <ul class="card" style="max-width: 22rem;">
   <li>Renew passport</li>
   <li>Dentist checkup</li>
@@ -38,7 +38,7 @@ a hover fill on its own; no `--clickable` modifier to remember.
 
 <figure class="example">
 <figcaption>Clickable rows</figcaption>
-<div>
+<div data-surface="sunken">
 <ul class="card" style="max-width: 22rem;">
   <li><button>Tax return 2025.pdf</button></li>
   <li><button>Warranty card.pdf</button></li>
@@ -60,7 +60,7 @@ patterns for it in context).
 
 <figure class="example">
 <figcaption>Leading icon, trailing meta</figcaption>
-<div>
+<div data-surface="sunken">
 <ul class="card" style="max-width: 24rem;">
   <li>
     <span class="avatar" data-square>
diff --git a/_components/card.md b/_components/card.md
index 2bc20bf..775bbf1 100644
--- a/_components/card.md
+++ b/_components/card.md
@@ -1,8 +1,9 @@
 ---
 title: Card
 summary: >-
-  Flat surface, hairline border, radius-lg. Elevation is opt-in, reserved for
-  the one focused card in a view — a dialog, the primary capture card.
+  Flat surface, no border, radius-lg. A step lighter than the page marks the
+  edge. Elevation is opt-in, reserved for the one focused card in a view — a
+  dialog, the primary capture card.
 ---
 
 A `<div>`/`<article>` is too generic to style bare, so Card keeps one
@@ -31,7 +32,7 @@ it that has no element of its own to hang a selector on.
 
 <figure class="example">
 <figcaption>Content tile</figcaption>
-<div>
+<div data-surface="sunken">
 <article class="card" style="max-width: 18rem;">
   <div class="card-body">
     <p class="type-label" style="margin:0;">Recommended</p>
@@ -69,7 +70,7 @@ li` descendant selector, no second class needed.
 
 <figure class="example">
 <figcaption>Card of rows</figcaption>
-<div>
+<div data-surface="sunken">
 <ul class="card" style="max-width: 22rem;">
   <li>Dishwasher manual</li>
   <li>Sofa receipt</li>
diff --git a/_components/icon-button.md b/_components/icon-button.md
index 4e20a41..4bb6f2c 100644
--- a/_components/icon-button.md
+++ b/_components/icon-button.md
@@ -7,10 +7,11 @@ summary: >-
 
 ## Variants
 
-`ghost` is the default and transparent. `outline` is a bordered surface, for
-an icon button sitting alone rather than in a toolbar. `accent` is a soft
-accent tint, for a toggled or active state — the segmented-tabs pattern this
-system does not otherwise reach for.
+`ghost` is the default and transparent. `outline` is a raised fill (no
+border — the name is kept for API compatibility, not for what it looks
+like), for an icon button sitting alone rather than in a toolbar. `accent`
+is a soft accent tint, for a toggled or active state — the segmented-tabs
+pattern this system does not otherwise reach for.
 
 A square icon-only button is still a `<button>`, but there is no attribute
 that tells it apart from a plain [Button](<%= relative_url('/components/button/') %>)
diff --git a/_foundations/color.md b/_foundations/color.md
index 532fb78..a8462dc 100644
--- a/_foundations/color.md
+++ b/_foundations/color.md
@@ -631,12 +631,13 @@ and checked by hand rather than by a build-time test.
     and de-emphasized metadata, never body copy — so this is a real,
     intentional property of the palette, not a bug to patch by darkening the
     step.
-    <strong>Borders</strong> — <code>--gl-color-border-hairline</code> and
+    <strong>Dividers</strong> — <code>--gl-color-border-hairline</code> and
     <code>--gl-color-border-default</code> sit well under the 3:1 that WCAG
-    1.4.11 asks of a meaningful boundary. Hairline (1px) borders and dividers
-    do most of the elevation work here — borders are deliberately quiet, and
-    this system never claims a 3:1 bar for them, so this contract does not
-    invent one.
+    1.4.11 asks of a meaningful boundary. That's deliberate: a bounded
+    surface in this system reads by surface contrast, not a border, so these
+    tokens are reserved for dividers inside a surface (a CardRow, a table
+    rule) — never a boundary around one — and this system never claims a
+    3:1 bar for them, so this contract does not invent one.
   </p>
 </div>
 
diff --git a/_foundations/elevation.md b/_foundations/elevation.md
index 41d5c92..c2175ea 100644
--- a/_foundations/elevation.md
+++ b/_foundations/elevation.md
@@ -1,15 +1,24 @@
 ---
 title: Elevation
 summary: >-
-  Two shadow levels only. Hairline (1px) borders do most of the elevation
-  work in this system; shadow is reserved for the one floating layer in a view.
+  Two shadow levels only. A bounded surface reads by being a step lighter
+  than what's behind it, not by a border around its edge; shadow is reserved
+  for the one floating layer in a view.
 ---
 
-## Borders do the work
+## Surface contrast does the work
 
-This system's own rule: hairline (1px) borders and dividers do most of the
-elevation work. A flat, bordered [Card](<%= relative_url('/components/card/') %>)
-is the default everywhere. Shadow is the exception, not the baseline.
+This system's own rule: no border marks the edge of a bounded surface. A
+flat [Card](<%= relative_url('/components/card/') %>) is the default
+everywhere — `--gl-color-surface-card` is one neutral step lighter than
+`--gl-color-surface-page` around it, and that tonal step is what reads as
+"a card," not an outline. Shadow is the exception, not the baseline.
+
+Hairlines have not disappeared from the system — a
+[CardRow](<%= relative_url('/components/card-row/') %>) still divides from
+its neighbor on one, a table still rules its rows, an underline tab still
+sits on one — they just no longer wrap a whole surface. A divider inside a
+card; never a border around one.
 
 ## The two levels
 
@@ -32,7 +41,7 @@ is the default everywhere. Shadow is the exception, not the baseline.
 <article class="card">
   <div class="card-body">
     <h3 style="font-size: var(--gl-step--1);">Flat</h3>
-    <p>The default. A hairline border, no shadow.</p>
+    <p>The default. A step lighter than the page, no border, no shadow.</p>
   </div>
 </article>
 <article class="card" data-elevated>
@@ -46,7 +55,7 @@ is the default everywhere. Shadow is the exception, not the baseline.
 <pre><code>&lt;article class="card"&gt;
   &lt;div class="card-body"&gt;
     &lt;h3&gt;Flat&lt;/h3&gt;
-    &lt;p&gt;The default. A hairline border, no shadow.&lt;/p&gt;
+    &lt;p&gt;The default. A step lighter than the page, no border, no shadow.&lt;/p&gt;
   &lt;/div&gt;
 &lt;/article&gt;
 &lt;article class="card" data-elevated&gt;
@@ -69,7 +78,8 @@ tokens still apply; they simply stop being the primary signal.
 
 - **At most one `--gl-shadow-float` on screen.** If two things both claim to
   be the topmost layer, neither is.
-- **Border or shadow, not both, for a given surface's edge.** A card that
-  both borders and floats looks like a sticker.
+- **No border around a bounded surface, ever.** Surface contrast does the
+  identifying work a border would; a card that borders and floats looks like
+  a sticker.
 - **Never animate a shadow's blur.** If a floated element needs to arrive,
   animate its `opacity`, or do not animate it at all.
diff --git a/_foundations/space.md b/_foundations/space.md
index a51bcad..c9f2cde 100644
--- a/_foundations/space.md
+++ b/_foundations/space.md
@@ -70,7 +70,7 @@ summary: >-
 
 <figure class="example">
 <figcaption>The same card at three densities</figcaption>
-<div data-layout="grid">
+<div data-layout="grid" data-surface="sunken">
 <article class="card">
   <div class="card-body" style="gap: var(--gl-space-3xs); padding: var(--gl-space-xs);">
     <h3 style="font-size: var(--gl-step--1);">Compact</h3>
diff --git a/_sass/components/badge.css b/_sass/components/badge.css
index a3772cd..af63cb1 100644
--- a/_sass/components/badge.css
+++ b/_sass/components/badge.css
@@ -1,35 +1,38 @@
 /* Badge
-   Mono, uppercase, tracked — the catalog-label convention for status and
-   meta values (SAVED, OVERDUE, RECOMMENDED). A label, never a button.
+   A catalog mark, not a tinted pill: a small ink square in the tone colour
+   plus mono uppercase text, on no background. No border, no radius — status
+   reads as a marginal annotation on the row it belongs to, not a control.
 
    A <span> is too generic to style globally — it is used all over running
    prose for unrelated reasons — so Badge gets the one sanctioned class this
    shape needs. Tone is an attribute, not a modifier class. */
 
 .badge {
-  --_bg: var(--gl-color-surface-fill);
   --_fg: var(--gl-color-text-secondary);
-  --_border: var(--gl-color-border-hairline);
 
   display: inline-flex;
   align-items: center;
-  gap: 0.25rem;
-  padding: 0.1875rem 0.5rem;
-  border: 1px solid var(--_border);
-  border-radius: var(--gl-radius-sm);
-  background: var(--_bg);
+  gap: 0.375rem;
   color: var(--_fg);
   font-family: var(--gl-font-mono);
   font-size: var(--gl-step--2);
+  font-weight: 500;
   text-transform: uppercase;
-  letter-spacing: 0.06em;
+  letter-spacing: 0.09em;
   line-height: 1;
   white-space: nowrap;
 }
+.badge::before {
+  content: "";
+  width: 0.375rem;
+  height: 0.375rem;
+  flex: none;
+  background: var(--_fg);
+}
 
-.badge[data-tone="accent"]  { --_bg: var(--gl-color-accent-soft);  --_fg: var(--gl-color-accent-ink);  --_border: transparent; }
-.badge[data-tone="success"] { --_bg: var(--gl-color-success-bg);   --_fg: var(--gl-color-success);      --_border: transparent; }
-.badge[data-tone="danger"]  { --_bg: var(--gl-color-danger-bg);    --_fg: var(--gl-color-danger);       --_border: transparent; }
+.badge[data-tone="accent"]  { --_fg: var(--gl-color-accent-ink); }
+.badge[data-tone="success"] { --_fg: var(--gl-color-success); }
+.badge[data-tone="danger"]  { --_fg: var(--gl-color-danger); }
 
 .badge-set {
   display: flex;
@@ -49,9 +52,9 @@
   align-items: center;
   gap: 0.375rem;
   padding: 0.25rem 0.625rem;
+  border: none;
   border-radius: var(--gl-radius-sm);
   background: var(--gl-color-surface-fill);
-  border: 1px solid var(--gl-color-border-default);
   color: var(--gl-color-text-secondary);
   font-family: var(--gl-font-mono);
   font-size: var(--gl-step--2);
diff --git a/_sass/components/button.css b/_sass/components/button.css
index 2a3cd87..0ca79ca 100644
--- a/_sass/components/button.css
+++ b/_sass/components/button.css
@@ -1,7 +1,10 @@
 /* Button
-   A flat, quiet button that recedes rather than performs — no gradients, no
-   shine. Variants: default, primary, dark, ghost, danger. Sizes: sm, md
-   (default), lg — padding and font step only, weight and radius stay put.
+   No border, no ornament — hierarchy is ink density, not an outline. A
+   STAMP (primary, dark, danger) is a solid block of colour; a QUIET action
+   (default, ghost) carries no fill at rest and picks up a flat tint of the
+   stock on hover, the same gesture as a CardRow. Variants: default, primary,
+   dark, ghost, danger. Sizes: sm, md (default), lg — padding and font step
+   only, weight and radius stay put.
 
    The contract is the element itself: a bare <button> is styled directly, no
    class required. An <a> that acts like a button (navigates rather than
@@ -13,9 +16,8 @@
 
 button:not(.icon-button),
 a.btn {
-  --_bg: var(--gl-color-surface-card);
+  --_bg: transparent;
   --_fg: var(--gl-color-text-primary);
-  --_border: var(--gl-color-border-default);
   --_pad: var(--gl-space-xs) var(--gl-space-s);
   --_font: var(--gl-step--1);
 
@@ -24,25 +26,39 @@ a.btn {
   justify-content: center;
   gap: var(--gl-space-2xs);
   padding: var(--_pad);
-  border: 1px solid var(--_border);
+  border: none;
   border-radius: var(--gl-radius-md);
   background: var(--_bg);
   color: var(--_fg);
-  font-family: var(--gl-font-sans);
+  font-family: var(--gl-font-mono);
   font-size: var(--_font);
-  font-weight: 550;
-  letter-spacing: -0.01em;
-  line-height: 1.2;
+  font-weight: 500;
+  letter-spacing: 0.01em;
+  line-height: 1.15;
   text-align: center;
   text-decoration: none;
   white-space: nowrap;
   cursor: pointer;
-  transition: filter var(--gl-dur-fast) var(--gl-ease),
-              border-color var(--gl-dur-fast) var(--gl-ease);
+  transition: background-color var(--gl-dur-fast) var(--gl-ease),
+              color var(--gl-dur-fast) var(--gl-ease),
+              filter var(--gl-dur-fast) var(--gl-ease);
+}
+
+/* Quiet variants (default, ghost) carry no fill at rest; hovering picks up
+   a flat tint of the stock instead of darkening a border that isn't there. */
+:is(button:not(.icon-button), a.btn):not([data-variant="primary"]):not([data-variant="dark"]):not([data-variant="danger"]):hover:not(:disabled):not([aria-disabled="true"]) {
+  background: var(--gl-color-surface-fill);
+  color: var(--gl-color-text-primary);
 }
 
-:is(button:not(.icon-button), a.btn):hover:not(:disabled):not([aria-disabled="true"]) { filter: brightness(0.96); }
-:is(button:not(.icon-button), a.btn):active:not(:disabled):not([aria-disabled="true"]) { filter: brightness(0.92); }
+/* Stamp variants (primary, dark, danger) are already ink — hovering just
+   darkens the fill in place. */
+:is(button:not(.icon-button), a.btn)[data-variant="primary"]:hover:not(:disabled):not([aria-disabled="true"]),
+:is(button:not(.icon-button), a.btn)[data-variant="dark"]:hover:not(:disabled):not([aria-disabled="true"]),
+:is(button:not(.icon-button), a.btn)[data-variant="danger"]:hover:not(:disabled):not([aria-disabled="true"]) { filter: brightness(0.96); }
+:is(button:not(.icon-button), a.btn)[data-variant="primary"]:active:not(:disabled):not([aria-disabled="true"]),
+:is(button:not(.icon-button), a.btn)[data-variant="dark"]:active:not(:disabled):not([aria-disabled="true"]),
+:is(button:not(.icon-button), a.btn)[data-variant="danger"]:active:not(:disabled):not([aria-disabled="true"]) { filter: brightness(0.92); }
 
 button:not(.icon-button):disabled,
 :is(button:not(.icon-button), a.btn)[aria-disabled="true"] {
@@ -53,7 +69,6 @@ button:not(.icon-button):disabled,
 :is(button:not(.icon-button), a.btn)[data-variant="primary"] {
   --_bg: var(--gl-color-accent);
   --_fg: var(--gl-color-accent-fg);
-  --_border: var(--gl-color-accent);
 }
 
 /* Reserved for the single most-committing action in a view — a final Save,
@@ -61,13 +76,12 @@ button:not(.icon-button):disabled,
 :is(button:not(.icon-button), a.btn)[data-variant="dark"] {
   --_bg: var(--gl-color-text-primary);
   --_fg: var(--gl-color-surface-page);
-  --_border: var(--gl-color-text-primary);
 }
 
+/* Same quiet block as default, one step further back: text-secondary at
+   rest instead of text-primary. */
 :is(button:not(.icon-button), a.btn)[data-variant="ghost"] {
-  --_bg: transparent;
-  --_fg: var(--gl-color-text-primary);
-  --_border: transparent;
+  --_fg: var(--gl-color-text-secondary);
 }
 
 /* The source hardcodes this label white rather than deriving it — danger
@@ -77,7 +91,6 @@ button:not(.icon-button):disabled,
 :is(button:not(.icon-button), a.btn)[data-variant="danger"] {
   --_bg: var(--gl-color-danger);
   --_fg: var(--gl-color-accent-fg);
-  --_border: var(--gl-color-danger);
 }
 
 :is(button:not(.icon-button), a.btn)[data-size="sm"] { --_pad: 0.375rem 0.75rem; --_font: 0.8125rem; }
@@ -86,7 +99,10 @@ button:not(.icon-button):disabled,
 :is(button:not(.icon-button), a.btn)[data-block] { width: 100%; }
 
 /* Button group — [role="group"] is already the correct ARIA role for a
-   toolbar of related buttons, so it doubles as the styling hook for free. */
+   toolbar of related buttons, so it doubles as the styling hook for free.
+   A hairline divider stands in for the border the buttons themselves no
+   longer carry — without one, two adjacent quiet buttons would read as a
+   single wide button. */
 [role="group"] {
   display: inline-flex;
   isolation: isolate;
@@ -94,7 +110,7 @@ button:not(.icon-button):disabled,
 [role="group"] > button { border-radius: 0; }
 [role="group"] > button:first-child { border-start-start-radius: var(--gl-radius-md); border-end-start-radius: var(--gl-radius-md); }
 [role="group"] > button:last-child { border-start-end-radius: var(--gl-radius-md); border-end-end-radius: var(--gl-radius-md); }
-[role="group"] > button + button { margin-inline-start: -1px; }
+[role="group"] > button + button { border-inline-start: 1px solid var(--gl-color-border-hairline); }
 [role="group"] > button:hover,
 [role="group"] > button:focus-visible { z-index: 1; }
 
@@ -105,7 +121,6 @@ button:not(.icon-button):disabled,
 .icon-button {
   --_size: 2.125rem;
   --_bg: transparent;
-  --_border: transparent;
   --_fg: var(--gl-color-text-secondary);
 
   display: inline-flex;
@@ -115,7 +130,7 @@ button:not(.icon-button):disabled,
   height: var(--_size);
   padding: 0;
   flex: none;
-  border: 1px solid var(--_border);
+  border: none;
   border-radius: var(--gl-radius-md);
   background: var(--_bg);
   color: var(--_fg);
@@ -123,11 +138,13 @@ button:not(.icon-button):disabled,
   transition: background-color var(--gl-dur-fast) var(--gl-ease),
               color var(--gl-dur-fast) var(--gl-ease);
 }
-.icon-button:hover:not(:disabled) { background: var(--gl-color-surface-fill-2); }
+.icon-button:hover:not(:disabled) { background: var(--gl-color-surface-fill); }
 .icon-button:disabled { opacity: 0.5; cursor: default; }
 
 .icon-button[data-size="sm"] { --_size: 1.75rem; }
 .icon-button[data-size="lg"] { --_size: 2.5rem; }
 
-.icon-button[data-variant="outline"] { --_bg: var(--gl-color-surface-card); --_border: var(--gl-color-border-default); --_fg: var(--gl-color-text-primary); }
+/* No border on either variant — "outline" keeps its name for API
+   compatibility, but reads as a raised fill instead of a bordered box. */
+.icon-button[data-variant="outline"] { --_bg: var(--gl-color-surface-fill); --_fg: var(--gl-color-text-primary); }
 .icon-button[data-variant="accent"]  { --_bg: var(--gl-color-accent-soft); --_fg: var(--gl-color-accent-ink); }
diff --git a/_sass/components/card.css b/_sass/components/card.css
index 0c08c60..8e86580 100644
--- a/_sass/components/card.css
+++ b/_sass/components/card.css
@@ -1,7 +1,9 @@
 /* Card
-   Flat surface, hairline border, radius-lg. `[data-elevated]` is opt-in and
-   reserved for the one focused/primary card in a view — a dialog, the
-   primary capture card — flat is the default everywhere else.
+   Flat surface, no border, radius-lg. `--gl-color-surface-card` is one
+   neutral step lighter than the page around it — that tonal step, not an
+   outline, is what marks the edge. `[data-elevated]` is opt-in and reserved
+   for the one focused/primary card in a view — a dialog, the primary
+   capture card — flat is the default everywhere else.
 
    A <div>/<article> is too generic to select bare, so Card keeps one
    sanctioned class. When Card's job is holding a list of rows — the common
@@ -18,7 +20,7 @@
   padding: 0;
   list-style: none;
   background: var(--gl-color-surface-card);
-  border: 1px solid var(--gl-color-border-hairline);
+  border: none;
   border-radius: var(--gl-radius-lg);
   box-shadow: none;
   overflow: hidden;
@@ -93,8 +95,8 @@
   background: var(--gl-color-surface-fill);
 }
 
-.card[data-link] { transition: border-color var(--gl-dur-fast) var(--gl-ease), box-shadow var(--gl-dur-fast) var(--gl-ease); }
-.card[data-link]:hover { border-color: var(--gl-color-border-default); box-shadow: var(--gl-shadow-sm); }
+.card[data-link] { transition: box-shadow var(--gl-dur-fast) var(--gl-ease); }
+.card[data-link]:hover { box-shadow: var(--gl-shadow-sm); }
 .card[data-link]:focus-within { outline: 2px solid var(--gl-color-accent); outline-offset: 2px; }
 
 .card-grid {
diff --git a/rationale.md b/rationale.md
index eb8fdf4..0266df2 100644
--- a/rationale.md
+++ b/rationale.md
@@ -82,10 +82,11 @@ about 3.46:1 against the page in light mode, under the 4.5:1 floor for normal
 text. That is not a bug to paper over by darkening a real brand value; it is
 a documented, intentional property of the palette (see the
 [Color page](<%= relative_url('/foundations/color/') %>)), so the contract
-excludes it rather than silently forcing it to pass. Borders get the same
-treatment for the same reason: this system's own rule is that hairline
-borders do the elevation work, not high contrast, so it does not invent a
-3:1 border assertion it never claimed.
+excludes it rather than silently forcing it to pass. Dividers get the same
+treatment for the same reason: this system's own rule is that a bounded
+surface reads by surface contrast, not by a border, so hairlines are
+reserved for dividers inside a surface and this contract does not invent a
+3:1 assertion for a boundary the system doesn't draw.
 
 ## The four rules
 
diff --git a/refusals.md b/refusals.md
index 5e8f4dc..7ea3a7a 100644
--- a/refusals.md
+++ b/refusals.md
@@ -21,8 +21,7 @@ screen that breaks one is off-system.
 <h3>Surface &amp; elevation</h3>
 <ul>
 <li>No cream or beige page. The stock is warm but held close to neutral.</li>
-<li>No side-accent bar on a card, no four-sided border, no bordered card at all.</li>
-<li>No hairline border and soft shadow on the same element. One or the other.</li>
+<li>No side-accent bar on a card, no four-sided border, no border around a bounded surface at all — surface contrast does the identifying work.</li>
 <li>No decorative grid, stripe field, or radial glow. Flat color only.</li>
 <li>No radius above <code>--gl-radius-lg</code> on a card, no custom corner value outside the token scale.</li>
 <li>No dark theme with colored glows.</li>