mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-16 16:16:32 +03:00
* Give DESIGN.md a real type ramp so the design hook stops crying wolf The design hook fired on nearly every CSS file we touched. The cause was DESIGN.md's typography block: it declared seven named roles rather than a scale, and two of those roles used clamp(), which the extractor skipped outright. That left an allowlist of five sizes standing against the 86 distinct font sizes actually in use, so design-system-font-size flagged roughly 500 declarations. Editing any .astro page made it worse, because the companion-stylesheet scan re-reported the whole backlog. Extractor (cli/engine/design-system.mjs): - Read a typography.scale map as the enumerated ramp. - Read both clamp() endpoints as allowed sizes. These stay additive on purpose: clamp endpoints alone cannot switch the rule on, because a fully fluid system enumerates no discrete ramp and inferring one from its endpoints would flag every intermediate size. The existing abstention test still passes, and three new tests cover the added behavior. DESIGN.md: - Document a 19-step ramp, 8px through 72px at a 16px root. - Snap the five discrete role sizes onto ramp steps. This also fixes real drift. DESIGN.md claims to mirror kinpaku-tokens.css verbatim, but wordmark was 1.15rem in the CSS against 1.3rem documented, with tracking at 0.42em against 0.15em. Both are re-synced. Standardization, 64 declarations: - Six near-identical steps between 13.7px and 15.4px collapse onto 14 and 15. - .foundation-card-label, .designing-lane-mock-title and .designing-iterate-name each existed at two different sizes in two files. Now unified. - The wordmark rendered at four sizes (20.8, 18.4, 17, 16.8px). Now 18px, plus one deliberate smaller nav variant. Exemptions, for designs that are foreign on purpose: the antipattern-example fixtures, the neo-mirai case-study build, the periodic-table cell annotations in framework-viz.js (5 to 7px diagram geometry sitting at 2 to 3px offsets), and the .why-slop-* before-state card's Inter and gradient text. Verified by computed style across ten rendered pages: every element lands on a ramp step except clamp() values mid-interpolation, which is what fluid means. Full test suite and build validators pass. Generated provider output is deliberately left out; the sync workflow owns it. Prepared with AI assistance (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com> * Validate clamp() endpoints in usage, not just when reading DESIGN.md Reading clamp endpoints as documented steps without also checking them in source left an asymmetry: `isAllowedFontSizeRaw` returned true for anything failing the px/rem literal test, so `clamp(99rem, 1vw, 200rem)` passed. That is how `.ptable-symbol` at `clamp(1.45rem, 1.8vw, 1.8rem)` stayed invisible until someone measured computed styles, which is not a check the hook can run. Fluid values are now judged on their min and max. The viewport term interpolates between them and is never a fixed step, so it is left alone. Endpoints that cannot be resolved, such as var() or calc() or em, abstain rather than guess. Findings name the offending endpoint and use it as the ignore-value, because the whole clamp string is not actionable on its own. Turning the check on surfaced 22 fluid declarations that had never been looked at. Three used hero sizes above the ramp's 72px cap (80, 83.2 and 88px) alongside the display role's documented 89.6px max, so the top of the ramp was genuinely incomplete. Added the 80 and 88 steps, which gives the display end consistent 8px increments instead of 48/56/64/72 plus an orphan at 89.6, and fixes two declarations outright. The other 20 are snapped by a stated rule: nearest step, ties toward the smaller step, endpoints already matching a documented fluid role left as-is, and where nearest-step would make a breakpoint override meet or exceed its base, the next smaller step so the override still reduces. That last case applies once, to .designing-page-title. Also narrows the framework-viz.js waiver. The periodic-table cell annotations now carry two `impeccable-disable-line` comments naming the reason, instead of a config entry wildcarding the whole file for the rule. Inline waivers travel with the code and cannot silence future drift elsewhere in that file. Verified at 420px, 900px and 1600px across seven pages. The pinned ends are fully on-ramp; the only off-ramp values at 900px are the vw term mid-interpolation, which is what fluid means. Prepared with AI assistance (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com> * Address review: wordmark tracking picked the wrong side, stale ramp count Two review findings, both fair. Wordmark tracking (greptile, bugbot). This PR moved DESIGN.md's wordmark letterSpacing from 0.15em to 0.42em on the grounds that DESIGN.md claims to mirror kinpaku-tokens.css and the token read 0.42em. That was the wrong side to trust. `--ks-type-wordmark-track` has exactly one consumer, design-system.css:570, which is the specimen page. Every production lockup (.ks-wordmark, .kinpaku-chrome .site-header-brand-name, .footer-logo) hardcodes 0.15em, so 0.15em is what every visitor actually sees and what DESIGN.md already documented correctly before this PR touched it. Reverted the doc to 0.15em and moved the token to 0.15em as well, so the specimen now renders the same lockup as production instead of a wider one nothing else uses. Verified by computed style: header and specimen both report 18px with 2.7px tracking. No production visual change. Stale ramp count (copilot). The sidecar described an "18-step ramp, 8px through 72px". It went stale twice inside this PR, once when the 8 step was added and again when 80 and 88 were added for the hero display sizes. It is 21 steps, 8px through 88px. Prepared with AI assistance (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com> * Strip !important from the font-size ignore value Follow-on from the waiver wiring in the hook branch. The ignoreValue is what a `hooks ignore-value` waiver has to match, and `font-size: 1.4rem !important` emitted `1.4rem !important` while a plain declaration emitted `1.4rem`. Once font-size is a direct-value rule, that means the same size needs two different waivers depending on whether it carries a priority marker. font-family already strips the marker before matching, and there is a test for that. font-size now does the same. The snippet still shows the declaration as authored. Prepared with AI assistance (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com> * Have the wordmark rules consume their tokens instead of copying the values Follow-up to the tracking fix, and the residual half of what the reviewers were pointing at. `.ks-wordmark` and the kinpaku chrome lockup each repeated `1.125rem` and `0.15em` literally rather than reading `--ks-type-wordmark-size` and `--ks-type-wordmark-track`. That duplication is exactly how the token drifted to 0.42em while every production lockup stayed at 0.15em and nobody noticed, which is the confusion that started this thread. The values already agree, so this is a no-op visually and is verified as such: computed styles across the home, design-system, docs and changelog pages all still report 18px with 2.7px tracking. What changes is that there is now one place to edit, so the next tracking change cannot silently apply to the specimen page alone. Prepared with AI assistance (Claude Code). Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1683 lines
40 KiB
CSS
1683 lines
40 KiB
CSS
/* ============================================================================
|
|
Impeccable — Neo Kinpaku Design System
|
|
Restrained dark surface. Kinpaku gold and verdigris patina carry the brand.
|
|
No nested cards, no decorative chrome, no washed-out textures.
|
|
|
|
Brand-defining tokens (kinpaku, pale, rich, patina, champagne, text, font,
|
|
ease, vermilion) live in kinpaku-tokens.css and are inherited from :root.
|
|
Only page-specific neutrals (ink/surface shades, rule alphas, muted) stay
|
|
scoped here.
|
|
============================================================================ */
|
|
|
|
@import "./kinpaku-tokens.css";
|
|
/* Divider geometry, tone modifiers, and texture-fill modifiers — shared with
|
|
the homepage. Must stay at the top of the file because CSS @import is only
|
|
valid before any other rules. */
|
|
@import "./divider-patterns.css";
|
|
|
|
.kinpaku-system-page {
|
|
/* Legacy alias layer. All real values live in kinpaku-tokens.css at :root;
|
|
this page's selectors still reference the old short names (--ks-ink,
|
|
--ks-surface, --ks-muted, --ks-mute-deep), so we forward them to the
|
|
forward names. Phase 4 of the design-system rework will rename the
|
|
selectors and delete this block. */
|
|
--ks-ink: var(--ks-lacquer);
|
|
--ks-ink-deep: var(--ks-lacquer-deep);
|
|
--ks-surface: var(--ks-lacquer-raised);
|
|
--ks-muted: var(--ks-text-muted);
|
|
--ks-mute-deep: var(--ks-text-mute-deep);
|
|
|
|
color: var(--ks-text);
|
|
background: var(--ks-lacquer);
|
|
font-family: var(--ks-font);
|
|
font-weight: 300;
|
|
margin: 0;
|
|
}
|
|
|
|
.kinpaku-system-page *,
|
|
.kinpaku-system-page *::before,
|
|
.kinpaku-system-page *::after {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.kinpaku-system-page img,
|
|
.kinpaku-system-page svg {
|
|
display: block;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.kinpaku-system-page a:not(.ks-brand) {
|
|
color: inherit;
|
|
text-decoration: none;
|
|
}
|
|
|
|
/* Brand lockup — kinpaku gold on dark surfaces; html.light swaps to ink
|
|
(see light-mode.css) to match impeccable-logo-on-light.svg. */
|
|
.kinpaku-system-page a.ks-brand {
|
|
color: var(--ks-kinpaku);
|
|
}
|
|
|
|
.kinpaku-system-page a.ks-brand .ks-mark,
|
|
.kinpaku-system-page a.ks-brand .ks-wordmark {
|
|
color: inherit;
|
|
}
|
|
|
|
.kinpaku-system-page button,
|
|
.kinpaku-system-page input,
|
|
.kinpaku-system-page select {
|
|
font: inherit;
|
|
}
|
|
|
|
.kinpaku-system {
|
|
position: relative;
|
|
isolation: isolate;
|
|
}
|
|
|
|
/* Skip link */
|
|
.kinpaku-system-page .skip-link {
|
|
position: fixed;
|
|
top: -96px;
|
|
left: 50%;
|
|
z-index: 1000;
|
|
transform: translateX(-50%);
|
|
padding: 10px 16px;
|
|
border-radius: 2px;
|
|
color: var(--ks-ink-deep);
|
|
background: var(--ks-kinpaku);
|
|
font-weight: 500;
|
|
text-decoration: none;
|
|
transition: top 180ms var(--ks-ease);
|
|
}
|
|
.kinpaku-system-page .skip-link:focus { top: 16px; }
|
|
.kinpaku-system-page .skip-link:focus:not(:focus-visible) { top: -96px; }
|
|
|
|
/* ============================================================================
|
|
Hero
|
|
============================================================================ */
|
|
|
|
.ks-hero {
|
|
position: relative;
|
|
min-height: 100svh;
|
|
display: grid;
|
|
grid-template-rows: auto 1fr auto;
|
|
padding: 36px 56px 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.ks-hero-art {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 0;
|
|
background:
|
|
linear-gradient(90deg, var(--ks-ink) 0%, oklch(4% 0.004 95 / 0.65) 26%, transparent 48%, transparent 88%, var(--ks-ink) 100%),
|
|
linear-gradient(180deg, oklch(4% 0.004 95 / 0.35) 0%, transparent 35%, var(--ks-ink) 100%),
|
|
url("/assets/neo-kinpaku/candidates/finalists/m-01-v2-01.png") center / cover no-repeat;
|
|
filter: saturate(1.22) contrast(1.1);
|
|
}
|
|
|
|
/* Header */
|
|
.ks-topbar {
|
|
position: relative;
|
|
z-index: 2;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 32px;
|
|
}
|
|
|
|
/* Brand lockup (.ks-brand, .ks-mark, .ks-wordmark) is in kinpaku-kit.css. */
|
|
|
|
.ks-nav {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 38px;
|
|
}
|
|
|
|
.ks-nav a {
|
|
color: var(--ks-champagne);
|
|
font-size: 0.92rem;
|
|
text-decoration: none;
|
|
letter-spacing: 0.01em;
|
|
transition: color 180ms var(--ks-ease);
|
|
}
|
|
|
|
.ks-nav a:hover { color: var(--ks-kinpaku); }
|
|
|
|
.ks-nav a[aria-current="page"] {
|
|
color: var(--ks-kinpaku);
|
|
position: relative;
|
|
}
|
|
.ks-nav a[aria-current="page"]::after {
|
|
content: "";
|
|
position: absolute;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: -8px;
|
|
height: 1px;
|
|
background: var(--ks-kinpaku);
|
|
}
|
|
|
|
/* Hero body */
|
|
.ks-hero-body {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: grid;
|
|
align-content: center;
|
|
padding: 80px 0 96px;
|
|
max-width: 940px;
|
|
}
|
|
|
|
.ks-hero-eyebrow {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.32em;
|
|
text-transform: uppercase;
|
|
margin: 0 0 28px;
|
|
}
|
|
|
|
.ks-hero-wordmark {
|
|
display: block;
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-font-display);
|
|
font-weight: 100;
|
|
font-size: clamp(3rem, 7.2vw, 5.6rem);
|
|
line-height: 1;
|
|
letter-spacing: 0.22em;
|
|
margin: 0;
|
|
padding-right: 0.22em;
|
|
}
|
|
|
|
.ks-hero-line {
|
|
margin: 28px 0 0;
|
|
max-width: 540px;
|
|
color: var(--ks-champagne);
|
|
font-size: clamp(1rem, 1.4vw, 1.25rem);
|
|
font-weight: 300;
|
|
line-height: 1.55;
|
|
}
|
|
|
|
.ks-hero-actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 16px;
|
|
margin-top: 36px;
|
|
}
|
|
|
|
.ks-hero-note {
|
|
margin-top: 56px;
|
|
display: grid;
|
|
grid-template-columns: 56px minmax(0, 1fr);
|
|
gap: 18px;
|
|
align-items: start;
|
|
max-width: 480px;
|
|
color: var(--ks-muted);
|
|
font-size: 0.9rem;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.ks-hero-note-pin {
|
|
height: 40px;
|
|
border-top: 1px solid var(--ks-kinpaku);
|
|
border-left: 1px solid var(--ks-kinpaku);
|
|
position: relative;
|
|
}
|
|
.ks-hero-note-pin::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: -3px;
|
|
left: -3px;
|
|
width: 5px;
|
|
height: 5px;
|
|
border-radius: 999px;
|
|
background: var(--ks-kinpaku);
|
|
}
|
|
|
|
/* Category rail */
|
|
.ks-category-rail {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: grid;
|
|
grid-template-columns: repeat(5, 1fr);
|
|
border-top: 1px solid var(--ks-rule);
|
|
margin: 0 -56px;
|
|
background: linear-gradient(180deg, transparent, oklch(4% 0.004 95 / 0.8));
|
|
}
|
|
|
|
.ks-category-rail a {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 14px;
|
|
padding: 26px 16px;
|
|
color: var(--ks-champagne);
|
|
text-decoration: none;
|
|
font-size: 0.96rem;
|
|
font-weight: 300;
|
|
letter-spacing: 0.02em;
|
|
border-right: 1px solid var(--ks-rule);
|
|
transition: color 180ms var(--ks-ease);
|
|
}
|
|
|
|
.ks-category-rail a:last-child { border-right: 0; }
|
|
.ks-category-rail a:hover { color: var(--ks-kinpaku); }
|
|
|
|
.ks-category-rail svg {
|
|
width: 18px;
|
|
height: 18px;
|
|
flex: none;
|
|
color: var(--ks-kinpaku);
|
|
}
|
|
|
|
/* ============================================================================
|
|
Sections
|
|
============================================================================ */
|
|
|
|
/* Section scaffolding (.ks-section, .ks-section-head, .ks-section-eyebrow,
|
|
.ks-subsection, .ks-subsection-label, .ks-section-sub) is in
|
|
kinpaku-kit.css. */
|
|
|
|
/* Hero candidate gallery */
|
|
.ks-candidate-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 18px;
|
|
}
|
|
|
|
.ks-candidate {
|
|
position: relative;
|
|
margin: 0;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
background: var(--ks-ink-deep);
|
|
}
|
|
|
|
.ks-candidate img {
|
|
display: block;
|
|
width: 100%;
|
|
height: auto;
|
|
aspect-ratio: 3 / 2;
|
|
object-fit: cover;
|
|
}
|
|
|
|
.ks-icon-candidate img {
|
|
aspect-ratio: 1;
|
|
}
|
|
|
|
.ks-icon-family-label {
|
|
margin: 32px 0 14px;
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.72rem;
|
|
letter-spacing: 0.22em;
|
|
text-transform: uppercase;
|
|
color: var(--ks-kinpaku);
|
|
font-weight: 400;
|
|
}
|
|
|
|
.ks-icon-family-label:first-of-type {
|
|
margin-top: 4px;
|
|
}
|
|
|
|
/* Hand-drawn icon-mark concept tiles. Each tile shows the candidate inside the
|
|
actual 38px icon box so it's evaluated at the size it'd ship at. */
|
|
.ks-icon-concepts {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
|
gap: 18px;
|
|
}
|
|
|
|
.ks-icon-concept {
|
|
margin: 0;
|
|
display: grid;
|
|
gap: 18px;
|
|
justify-items: center;
|
|
padding: 36px 18px 18px;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
background: var(--ks-ink-deep);
|
|
}
|
|
|
|
.ks-icon-concept-box {
|
|
width: 38px;
|
|
height: 38px;
|
|
display: grid;
|
|
place-items: center;
|
|
border: 1px solid var(--ks-kinpaku);
|
|
color: var(--ks-kinpaku);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.ks-icon-concept-box svg {
|
|
width: 14px;
|
|
height: 22px;
|
|
display: block;
|
|
}
|
|
|
|
.ks-icon-concept figcaption {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--ks-muted);
|
|
text-align: center;
|
|
}
|
|
|
|
/* Canonical mark, shown at a range of sizes. No container box — the tile is
|
|
the mark. */
|
|
.ks-mark-scale {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: 40px;
|
|
}
|
|
.ks-mark-scale-item {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 14px;
|
|
margin: 0;
|
|
}
|
|
.ks-mark-glyph {
|
|
display: inline-grid;
|
|
place-items: center;
|
|
color: var(--ks-kinpaku);
|
|
}
|
|
.ks-mark-glyph svg { width: 100%; height: 100%; display: block; }
|
|
.ks-mark-scale-item figcaption {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.62rem;
|
|
letter-spacing: 0.14em;
|
|
color: var(--ks-muted);
|
|
}
|
|
|
|
.ks-candidate figcaption {
|
|
position: absolute;
|
|
left: 10px;
|
|
top: 10px;
|
|
padding: 2px 8px;
|
|
background: oklch(4% 0.004 95 / 0.74);
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
border: 1px solid var(--ks-kinpaku);
|
|
border-radius: 2px;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.ks-candidate.is-kept figcaption {
|
|
color: var(--ks-patina);
|
|
border-color: var(--ks-patina);
|
|
}
|
|
|
|
/* Keyed (transparent) candidates: split background to reveal alpha */
|
|
.ks-candidate-keyed-stack {
|
|
position: relative;
|
|
aspect-ratio: 3 / 2;
|
|
}
|
|
|
|
.ks-candidate-keyed-stack img {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
z-index: 2;
|
|
}
|
|
|
|
.ks-candidate-keyed-checker {
|
|
position: absolute;
|
|
inset: 0;
|
|
z-index: 1;
|
|
background:
|
|
linear-gradient(90deg, var(--ks-ink-deep) 50%, transparent 50%),
|
|
linear-gradient(90deg, transparent 50%, var(--ks-graphite) 50%);
|
|
background-size: 100% 100%, 100% 100%;
|
|
}
|
|
|
|
@media (max-width: 1080px) {
|
|
.ks-candidate-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
}
|
|
@media (max-width: 640px) {
|
|
.ks-candidate-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* ============================================================================
|
|
Buttons
|
|
============================================================================ */
|
|
|
|
/* Buttons (.ks-button, .ks-button-primary, .ks-button-secondary,
|
|
.ks-button-ghost, .ks-button-disabled, .ks-button-arrow, .ks-button-row,
|
|
focus-visible) are in kinpaku-kit.css. */
|
|
|
|
/* ============================================================================
|
|
Foundations: Color swatches (flat, no card chrome)
|
|
============================================================================ */
|
|
|
|
.ks-swatch-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
gap: 28px;
|
|
}
|
|
|
|
.ks-swatch {
|
|
display: grid;
|
|
gap: 12px;
|
|
}
|
|
|
|
.ks-swatch-chip {
|
|
width: 100%;
|
|
aspect-ratio: 5 / 4;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.ks-swatch-chip.is-kinpaku {
|
|
border-color: transparent;
|
|
background: url("/assets/neo-kinpaku/kinpaku-gold-leaf.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.18) contrast(1.08);
|
|
}
|
|
|
|
.ks-swatch-chip.is-patina {
|
|
border-color: transparent;
|
|
background: url("/assets/neo-kinpaku/verdigris-patina.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.2) contrast(1.06);
|
|
}
|
|
|
|
.ks-swatch-chip.is-ink { background: var(--ks-ink); border-color: oklch(20% 0.006 95); }
|
|
.ks-swatch-chip.is-surface { background: var(--ks-surface); }
|
|
.ks-swatch-chip.is-champagne { background: var(--ks-champagne); border-color: transparent; }
|
|
.ks-swatch-chip.is-vermilion { background: var(--ks-vermilion); border-color: transparent; }
|
|
|
|
.ks-swatch-name {
|
|
display: block;
|
|
color: var(--ks-champagne);
|
|
font-size: 0.92rem;
|
|
font-weight: 400;
|
|
}
|
|
|
|
.ks-swatch-role {
|
|
display: block;
|
|
color: var(--ks-muted);
|
|
font-size: 0.78rem;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
.ks-swatch-value {
|
|
display: block;
|
|
color: var(--ks-mute-deep);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Foundations: Type specs (no card)
|
|
============================================================================ */
|
|
|
|
.ks-type-stack {
|
|
display: grid;
|
|
gap: 28px;
|
|
}
|
|
|
|
.ks-type-row {
|
|
display: grid;
|
|
grid-template-columns: 120px 1fr;
|
|
gap: 32px;
|
|
align-items: baseline;
|
|
padding-bottom: 28px;
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
}
|
|
|
|
.ks-type-row:last-child {
|
|
padding-bottom: 0;
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.ks-type-label {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.24em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-type-spec-line {
|
|
color: var(--ks-muted);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.06em;
|
|
margin-top: 8px;
|
|
}
|
|
|
|
/* Type samples — render the production scale, full strength. The samples
|
|
read directly from --ks-type-* tokens so the design-system page literally
|
|
shows what the homepage ships. data-scale on each sample selects which
|
|
token family applies. */
|
|
|
|
.ks-type-sample {
|
|
margin: 0;
|
|
font-family: var(--ks-font);
|
|
color: var(--ks-text);
|
|
}
|
|
|
|
.ks-type-sample[data-scale="wordmark"] {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-font-display);
|
|
font-weight: var(--ks-type-display-weight);
|
|
font-size: var(--ks-type-wordmark-size);
|
|
letter-spacing: var(--ks-type-wordmark-track);
|
|
text-transform: uppercase;
|
|
line-height: 1;
|
|
}
|
|
|
|
.ks-type-sample[data-scale="display"] {
|
|
color: var(--ks-champagne);
|
|
font-family: var(--ks-font-display);
|
|
font-weight: var(--ks-type-display-weight);
|
|
font-size: var(--ks-type-display-size);
|
|
line-height: var(--ks-type-display-line);
|
|
letter-spacing: var(--ks-type-display-track);
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.ks-type-sample[data-scale="headline"] {
|
|
color: var(--ks-champagne);
|
|
font-family: var(--ks-font-display);
|
|
font-weight: var(--ks-type-headline-weight);
|
|
font-size: var(--ks-type-headline-size);
|
|
line-height: var(--ks-type-headline-line);
|
|
text-wrap: balance;
|
|
}
|
|
|
|
.ks-type-sample[data-scale="body"] {
|
|
color: var(--ks-text);
|
|
font-size: var(--ks-type-body-size);
|
|
line-height: var(--ks-type-body-line);
|
|
max-width: 65ch;
|
|
}
|
|
|
|
.ks-type-sample[data-scale="mono"] {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: var(--ks-type-mono-size);
|
|
letter-spacing: var(--ks-type-mono-track);
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Foundations: Paired material + solid swatches
|
|
The two brand anchors (kinpaku, verdigris) each get a side-by-side display
|
|
of their material texture and their solid color token. Reinforces that
|
|
"material" and "color" are two sides of the same anchor, not separate
|
|
categories.
|
|
============================================================================ */
|
|
|
|
.ks-pair-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 28px;
|
|
}
|
|
|
|
.ks-pair {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
column-gap: 4px;
|
|
row-gap: 12px;
|
|
}
|
|
|
|
.ks-pair-chip {
|
|
width: 100%;
|
|
aspect-ratio: 5 / 4;
|
|
border-radius: 2px;
|
|
grid-row: 1;
|
|
border: 1px solid transparent;
|
|
}
|
|
|
|
.ks-pair-chip.is-kinpaku-leaf {
|
|
background: url("/assets/neo-kinpaku/kinpaku-gold-leaf.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.18) contrast(1.08);
|
|
}
|
|
|
|
.ks-pair-chip.is-kinpaku-solid {
|
|
background: var(--ks-kinpaku);
|
|
}
|
|
|
|
.ks-pair-chip.is-patina-leaf {
|
|
background: url("/assets/neo-kinpaku/verdigris-patina.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.2) contrast(1.06);
|
|
}
|
|
|
|
.ks-pair-chip.is-patina-solid {
|
|
background: var(--ks-patina);
|
|
}
|
|
|
|
.ks-pair-name {
|
|
grid-column: 1 / -1;
|
|
color: var(--ks-champagne);
|
|
font-size: 0.92rem;
|
|
font-weight: 400;
|
|
}
|
|
|
|
.ks-pair-role {
|
|
grid-column: 1 / -1;
|
|
color: var(--ks-muted);
|
|
font-size: 0.78rem;
|
|
line-height: 1.5;
|
|
margin-top: -6px;
|
|
}
|
|
|
|
.ks-pair-value {
|
|
grid-column: 1 / -1;
|
|
color: var(--ks-mute-deep);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
margin-top: -2px;
|
|
}
|
|
|
|
@media (max-width: 700px) {
|
|
.ks-pair-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* ============================================================================
|
|
Inline mono code chip (motion section, in-prose references to tokens)
|
|
============================================================================ */
|
|
|
|
.ks-mono-inline {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.8em;
|
|
color: var(--ks-kinpaku);
|
|
padding: 0.05em 0.4em;
|
|
border: 1px solid oklch(78% 0.12 82 / 0.18);
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Container patterns: Canonical bento showcase
|
|
Wraps a live .ks-bento at reduced height with a "Used in production"
|
|
annotation. The frame keeps the bento from breaking out of the section
|
|
because the doc's canonical sample is illustrative, not full-bleed.
|
|
============================================================================ */
|
|
|
|
.ks-canonical {
|
|
display: grid;
|
|
gap: 18px;
|
|
}
|
|
|
|
.ks-canonical-frame {
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
padding: 16px;
|
|
background: oklch(0.10 0.005 95);
|
|
overflow: hidden;
|
|
}
|
|
|
|
/* Override the .ks-bento's top/bottom border (which is brand-bearing 8px
|
|
plinth) for the in-doc sample so the frame's border carries the contain. */
|
|
.ks-canonical-bento {
|
|
border-top-width: 0;
|
|
border-bottom-width: 0;
|
|
}
|
|
|
|
.ks-canonical-bento .ks-bento-tile {
|
|
padding: 24px;
|
|
gap: 8px;
|
|
}
|
|
|
|
.ks-canonical-foot {
|
|
display: grid;
|
|
gap: 6px;
|
|
color: var(--ks-muted);
|
|
font-size: 0.88rem;
|
|
line-height: 1.55;
|
|
max-width: 78ch;
|
|
}
|
|
|
|
.ks-canonical-foot strong {
|
|
color: var(--ks-champagne);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.ks-canonical-meta {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.72rem;
|
|
letter-spacing: 0.04em;
|
|
color: var(--ks-mute-deep);
|
|
margin: 0;
|
|
}
|
|
|
|
.ks-canonical-used {
|
|
color: var(--ks-kinpaku);
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.18em;
|
|
}
|
|
|
|
.ks-canonical-meta a {
|
|
color: var(--ks-champagne);
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
}
|
|
|
|
.ks-canonical-meta a:hover {
|
|
color: var(--ks-kinpaku);
|
|
border-bottom-color: var(--ks-kinpaku);
|
|
}
|
|
|
|
/* ============================================================================
|
|
Foundations: Logo download tiles
|
|
============================================================================ */
|
|
|
|
.ks-logo-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 18px;
|
|
}
|
|
|
|
.ks-logo-tile {
|
|
margin: 0;
|
|
display: grid;
|
|
gap: 0;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.ks-logo-tile img {
|
|
display: block;
|
|
width: auto;
|
|
max-width: 78%;
|
|
height: auto;
|
|
margin: 56px auto;
|
|
}
|
|
|
|
.ks-logo-tile.is-dark {
|
|
background: oklch(7% 0.006 95);
|
|
}
|
|
|
|
.ks-logo-tile.is-light {
|
|
background: oklch(94% 0.012 82);
|
|
}
|
|
|
|
.ks-logo-tile figcaption {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
padding: 14px 18px;
|
|
border-top: 1px solid var(--ks-rule);
|
|
background: oklch(9% 0.006 95);
|
|
color: var(--ks-muted);
|
|
}
|
|
|
|
.ks-logo-tile-label {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--ks-kinpaku);
|
|
}
|
|
|
|
.ks-logo-tile-links {
|
|
display: flex;
|
|
gap: 14px;
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.72rem;
|
|
}
|
|
|
|
.ks-logo-tile-links a {
|
|
color: var(--ks-text);
|
|
text-decoration: none;
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
padding-bottom: 1px;
|
|
transition: color 160ms ease, border-color 160ms ease;
|
|
}
|
|
|
|
.ks-logo-tile-links a:hover {
|
|
color: var(--ks-kinpaku);
|
|
border-bottom-color: var(--ks-kinpaku);
|
|
}
|
|
|
|
.ks-logo-note {
|
|
margin: 18px 0 0;
|
|
color: var(--ks-muted);
|
|
font-size: 0.88rem;
|
|
line-height: 1.55;
|
|
max-width: 62ch;
|
|
}
|
|
|
|
@media (max-width: 720px) {
|
|
.ks-logo-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* ============================================================================
|
|
Container prototypes
|
|
Six framing approaches that group content without nesting card-in-card.
|
|
The .ksp-tile is the prototype's outer frame (only there so the user can
|
|
compare techniques side-by-side). The .ksp-stage is the dark surface each
|
|
prototype "lives on" — that's the real container under test.
|
|
============================================================================ */
|
|
|
|
.ks-container-prototypes {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 28px;
|
|
}
|
|
|
|
.ksp-tile {
|
|
margin: 0;
|
|
display: grid;
|
|
gap: 0;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
background: oklch(9% 0.006 95);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.ksp-tile-head {
|
|
display: grid;
|
|
grid-template-columns: auto auto 1fr;
|
|
align-items: baseline;
|
|
gap: 14px;
|
|
padding: 14px 22px;
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
background: oklch(11% 0.006 95);
|
|
font-family: var(--ks-mono);
|
|
}
|
|
|
|
.ksp-tile-id {
|
|
color: var(--ks-kinpaku);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ksp-tile-name {
|
|
color: var(--ks-champagne);
|
|
font-family: var(--ks-font);
|
|
font-size: 0.95rem;
|
|
}
|
|
|
|
.ksp-tile-desc {
|
|
color: var(--ks-muted);
|
|
font-size: 0.78rem;
|
|
text-align: right;
|
|
}
|
|
|
|
/* The "stage" is the lacquer surface each prototype sits on. Generous padding
|
|
so the framing technique has air to breathe; the real test is whether the
|
|
content feels grouped without sitting inside a competing card. */
|
|
.ksp-stage {
|
|
position: relative;
|
|
padding: 56px 48px;
|
|
min-height: 240px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.ksp-stage--dark {
|
|
background: var(--ks-ink);
|
|
}
|
|
|
|
/* Sample content typography — shared across all six prototypes so framing
|
|
is the only visual variable. */
|
|
.ksp-eyebrow {
|
|
margin: 0 0 12px;
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ksp-title {
|
|
margin: 0 0 12px;
|
|
color: var(--ks-champagne);
|
|
font-family: var(--ks-font);
|
|
font-weight: 300;
|
|
font-size: 1.5rem;
|
|
line-height: 1.15;
|
|
letter-spacing: -0.005em;
|
|
}
|
|
|
|
.ksp-body {
|
|
margin: 0;
|
|
color: var(--ks-text);
|
|
font-size: 0.95rem;
|
|
line-height: 1.55;
|
|
max-width: 46ch;
|
|
}
|
|
|
|
/* B · Numbered marginalia — large outlined number in the gutter. */
|
|
.ksp-style-b {
|
|
display: grid;
|
|
grid-template-columns: auto 1fr;
|
|
gap: 28px;
|
|
align-items: start;
|
|
}
|
|
|
|
.ksp-marginal-num {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-font);
|
|
font-weight: 300;
|
|
font-size: 4.5rem;
|
|
line-height: 0.9;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
/* F · Kinpaku slab anchor — tiny full-vibrancy gold-leaf chip behind the
|
|
eyebrow. The texture is brand-bearing, the rest is clean lacquer. */
|
|
.ksp-style-f .ksp-eyebrow--chip {
|
|
display: inline-block;
|
|
padding: 6px 14px;
|
|
margin-bottom: 16px;
|
|
color: var(--ks-ink-deep);
|
|
background: url("/assets/neo-kinpaku/kinpaku-gold-leaf.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.15) contrast(1.08);
|
|
font-weight: 600;
|
|
letter-spacing: 0.16em;
|
|
}
|
|
|
|
/* G · Tinted plinth — flat neutral lift. No border, no shadow, no inner
|
|
shape. Pure background-color step from the lacquer (7%) up to 17% neutral
|
|
gray. Zero chroma (the "0 0" in oklch) keeps it neutral so the gold accents
|
|
in the content carry the warmth on their own. The dark-mode equivalent of
|
|
the light-mode "raise content by 4% lightness" trick. */
|
|
.ksp-style-g {
|
|
background: oklch(0.17 0 0);
|
|
padding: 28px 32px;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.ks-container-prototypes { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
/* ============================================================================
|
|
Divider patterns (CSS-only, no image assets)
|
|
Each pattern uses currentColor or var(--ks-kinpaku) so the gold tone follows
|
|
the brand token. Use these on full-width section transitions or as accent
|
|
rules above eyebrow labels.
|
|
============================================================================ */
|
|
|
|
.ks-divider-stack {
|
|
display: grid;
|
|
gap: 36px;
|
|
}
|
|
|
|
.ksd-row {
|
|
margin: 0;
|
|
}
|
|
|
|
.ksd-row figcaption {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
color: var(--ks-muted);
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
/* Tone comparison row inside a divider figure: small label + the actual
|
|
divider, repeated for each of kinpaku / patina / plinth / textures. */
|
|
.ksd-tones {
|
|
display: grid;
|
|
gap: 14px;
|
|
}
|
|
.ksd-tone {
|
|
display: grid;
|
|
grid-template-columns: 72px 1fr;
|
|
gap: 18px;
|
|
align-items: center;
|
|
}
|
|
.ksd-tone-label {
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.6rem;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
color: var(--ks-muted);
|
|
}
|
|
|
|
/* ============================================================================
|
|
Foundations: Accent textures (full vibrancy, three only)
|
|
============================================================================ */
|
|
|
|
.ks-accent-stack {
|
|
display: grid;
|
|
gap: 28px;
|
|
}
|
|
|
|
.ks-accent-row {
|
|
display: grid;
|
|
gap: 14px;
|
|
}
|
|
|
|
.ks-accent-row-label {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.24em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-accent-row-label small {
|
|
color: var(--ks-muted);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-accent-band {
|
|
position: relative;
|
|
height: 96px;
|
|
overflow: hidden;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.ks-accent-band.is-leaf {
|
|
background: url("/assets/neo-kinpaku/kinpaku-gold-leaf.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.15) contrast(1.08);
|
|
}
|
|
|
|
.ks-accent-band.is-patina {
|
|
background: url("/assets/neo-kinpaku/verdigris-patina.png") 50% 50% / cover no-repeat;
|
|
filter: saturate(1.18) contrast(1.06);
|
|
}
|
|
|
|
.ks-accent-band.is-dust {
|
|
background: url("/assets/neo-kinpaku/gold-dust-rule.png") center / 100% 100% no-repeat;
|
|
filter: saturate(1.22) contrast(1.15) brightness(1.12);
|
|
}
|
|
|
|
/* ============================================================================
|
|
Navigation sample
|
|
============================================================================ */
|
|
|
|
.ks-nav-sample {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
min-height: 68px;
|
|
padding: 0 24px;
|
|
border-top: 1px solid var(--ks-rule);
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
}
|
|
|
|
.ks-nav-sample .ks-brand { gap: 14px; }
|
|
.ks-nav-sample .ks-mark { width: 32px; height: 32px; }
|
|
.ks-nav-sample .ks-mark svg { width: 27px; height: 27px; }
|
|
.ks-nav-sample .ks-wordmark { font-size: 0.78rem; }
|
|
|
|
.ks-nav-sample-mobile {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 24px;
|
|
min-height: 60px;
|
|
padding: 0 24px;
|
|
border-top: 1px solid var(--ks-rule);
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
margin-top: 28px;
|
|
max-width: 420px;
|
|
}
|
|
|
|
.ks-menu-button {
|
|
width: 36px;
|
|
height: 36px;
|
|
display: grid;
|
|
place-content: center;
|
|
gap: 6px;
|
|
background: transparent;
|
|
border: 0;
|
|
color: var(--ks-kinpaku);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.ks-menu-button span {
|
|
width: 22px;
|
|
height: 1px;
|
|
background: currentColor;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Actions: button row, states, form, tabs
|
|
============================================================================ */
|
|
|
|
/* .ks-button-row is in kinpaku-kit.css. */
|
|
|
|
.ks-state-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(120px, auto) 1fr;
|
|
gap: 16px 24px;
|
|
align-items: center;
|
|
max-width: 420px;
|
|
}
|
|
|
|
.ks-state-label {
|
|
color: var(--ks-muted);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/* Force pseudo-states for state showcase */
|
|
.ks-state-grid .ks-button-primary[data-state="hover"] {
|
|
background: var(--ks-kinpaku-pale);
|
|
border-color: var(--ks-kinpaku-pale);
|
|
}
|
|
.ks-state-grid .ks-button-primary[data-state="pressed"] {
|
|
background: oklch(72% 0.11 82);
|
|
border-color: oklch(72% 0.11 82);
|
|
}
|
|
|
|
/* Form controls (.ks-form-sample, .ks-toggle, .ks-checkbox, .ks-select) and
|
|
tabs (.ks-tabs, .ks-tab-list, .ks-tab-panel) are in kinpaku-kit.css. */
|
|
|
|
/* ============================================================================
|
|
Components: Audit Result Row, badges, tags, integration badges, pagination
|
|
============================================================================ */
|
|
|
|
.ks-audit-result {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 48px;
|
|
padding: 32px 36px 36px;
|
|
border-top: 1px solid var(--ks-rule);
|
|
margin-bottom: 64px;
|
|
}
|
|
|
|
.ks-audit-stat {
|
|
display: grid;
|
|
gap: 6px;
|
|
}
|
|
|
|
.ks-audit-stat-label {
|
|
color: var(--ks-muted);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.24em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-audit-stat-value {
|
|
font-weight: 300;
|
|
font-size: clamp(2.5rem, 4vw, 3rem);
|
|
line-height: 1;
|
|
letter-spacing: -0.01em;
|
|
}
|
|
.ks-audit-stat-value.is-warning { color: var(--ks-vermilion); }
|
|
.ks-audit-stat-value.is-improved { color: var(--ks-patina); }
|
|
.ks-audit-stat-value.is-ready { color: var(--ks-kinpaku); }
|
|
|
|
.ks-audit-stat-meta {
|
|
color: var(--ks-muted);
|
|
font-size: 0.84rem;
|
|
}
|
|
|
|
/* Badges (.ks-badge, .ks-badge-row) and tags (.ks-tag, .ks-tag-row) are in
|
|
kinpaku-kit.css. */
|
|
|
|
/* Integration badges */
|
|
.ks-integration-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 18px;
|
|
}
|
|
|
|
.ks-integration-badge {
|
|
width: 44px;
|
|
height: 44px;
|
|
display: grid;
|
|
place-items: center;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
color: var(--ks-champagne);
|
|
transition: border-color 180ms var(--ks-ease), color 180ms var(--ks-ease);
|
|
}
|
|
.ks-integration-badge:hover {
|
|
border-color: var(--ks-kinpaku);
|
|
color: var(--ks-kinpaku);
|
|
}
|
|
.ks-integration-badge svg { width: 20px; height: 20px; }
|
|
|
|
/* Pagination, toast/alert, icon button + tooltip, modal, empty state,
|
|
changelog row, skeleton (+ ks-shimmer keyframes) are all in kinpaku-kit.css.
|
|
Only the tooltip *trigger* wrapper (.ks-tooltip-sample) stays here as
|
|
page-specific doc presentation. */
|
|
|
|
.ks-tooltip-sample {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0;
|
|
padding: 22px 0;
|
|
}
|
|
|
|
.ks-tooltip-sample:hover .ks-tooltip {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Proof: Comparison + audit detail rows
|
|
============================================================================ */
|
|
|
|
.ks-proof-grid {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.6fr);
|
|
gap: 48px;
|
|
}
|
|
|
|
.ks-comparison {
|
|
position: relative;
|
|
}
|
|
|
|
.ks-comparison-head {
|
|
display: flex;
|
|
align-items: baseline;
|
|
justify-content: space-between;
|
|
margin-bottom: 18px;
|
|
}
|
|
|
|
.ks-comparison-head h3 {
|
|
margin: 0;
|
|
color: var(--ks-champagne);
|
|
font-size: 0.96rem;
|
|
font-weight: 400;
|
|
}
|
|
|
|
.ks-comparison-head span {
|
|
color: var(--ks-muted);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.18em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-comparison-stage {
|
|
position: relative;
|
|
aspect-ratio: 16 / 10;
|
|
overflow: hidden;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
background:
|
|
linear-gradient(180deg, oklch(8% 0.006 95), oklch(5% 0.004 95));
|
|
}
|
|
|
|
.ks-comparison-side {
|
|
position: absolute;
|
|
inset: 0;
|
|
padding: 28px;
|
|
display: grid;
|
|
align-items: center;
|
|
justify-items: center;
|
|
}
|
|
|
|
.ks-comparison-before {
|
|
background:
|
|
radial-gradient(circle at 50% 50%, oklch(60% 0.18 305 / 0.12), transparent 18rem),
|
|
linear-gradient(180deg, oklch(8% 0.006 95), oklch(5% 0.004 95));
|
|
}
|
|
|
|
.ks-comparison-after {
|
|
background:
|
|
radial-gradient(circle at 50% 50%, oklch(69% 0.105 190 / 0.1), transparent 18rem),
|
|
linear-gradient(180deg, oklch(8% 0.006 95), oklch(5% 0.004 95));
|
|
}
|
|
|
|
.ks-mini-ui {
|
|
width: min(360px, 88%);
|
|
padding: 18px;
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 4px;
|
|
background: var(--ks-surface);
|
|
}
|
|
|
|
.ks-mini-ui-before .ks-mini-orb {
|
|
width: 40px;
|
|
height: 40px;
|
|
border-radius: 999px;
|
|
background: linear-gradient(135deg, oklch(65% 0.22 285), oklch(54% 0.25 310));
|
|
margin-bottom: 14px;
|
|
}
|
|
.ks-mini-ui-before strong {
|
|
color: var(--ks-champagne);
|
|
font-size: 0.98rem;
|
|
font-weight: 500;
|
|
display: block;
|
|
}
|
|
.ks-mini-ui-before p {
|
|
margin: 6px 0 14px;
|
|
color: var(--ks-muted);
|
|
font-size: 0.82rem;
|
|
}
|
|
.ks-mini-ui-before .ks-mini-cta {
|
|
width: 100%;
|
|
min-height: 38px;
|
|
border: 0;
|
|
border-radius: 4px;
|
|
background: linear-gradient(90deg, oklch(62% 0.24 285), oklch(48% 0.22 315));
|
|
color: oklch(98% 0.01 285);
|
|
font-size: 0.86rem;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.ks-mini-ui-after {
|
|
border-color: var(--ks-kinpaku);
|
|
}
|
|
.ks-mini-ui-after .ks-mini-rule {
|
|
width: 64px;
|
|
height: 1px;
|
|
background: var(--ks-kinpaku);
|
|
margin-bottom: 14px;
|
|
}
|
|
.ks-mini-ui-after strong {
|
|
color: var(--ks-champagne);
|
|
font-size: 0.98rem;
|
|
font-weight: 400;
|
|
display: block;
|
|
}
|
|
.ks-mini-ui-after p {
|
|
margin: 6px 0 0;
|
|
color: var(--ks-muted);
|
|
font-size: 0.82rem;
|
|
}
|
|
|
|
.ks-comparison-divider {
|
|
position: absolute;
|
|
top: -6%;
|
|
left: 50%;
|
|
width: 140px;
|
|
height: 112%;
|
|
transform: translateX(-50%);
|
|
pointer-events: none;
|
|
z-index: 4;
|
|
background-image: url("/assets/neo-kinpaku/before-after-seam.png");
|
|
background-repeat: no-repeat;
|
|
background-position: center;
|
|
background-size: auto 100%;
|
|
filter: drop-shadow(0 0 16px oklch(77% 0.14 82 / 0.42)) saturate(1.22);
|
|
}
|
|
|
|
.ks-comparison-range {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
opacity: 0;
|
|
cursor: ew-resize;
|
|
margin: 0;
|
|
}
|
|
|
|
.ks-audit-rows {
|
|
display: grid;
|
|
gap: 0;
|
|
}
|
|
|
|
.ks-audit-row {
|
|
display: grid;
|
|
grid-template-columns: 70px 1fr auto;
|
|
gap: 18px;
|
|
align-items: center;
|
|
padding: 18px 0;
|
|
border-bottom: 1px solid var(--ks-rule);
|
|
}
|
|
.ks-audit-row:first-child { padding-top: 0; }
|
|
.ks-audit-row:last-child { border-bottom: 0; }
|
|
|
|
.ks-severity {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 6px;
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.ks-severity::before {
|
|
content: "";
|
|
width: 6px;
|
|
height: 6px;
|
|
border-radius: 999px;
|
|
}
|
|
|
|
.ks-severity.is-high { color: var(--ks-vermilion); }
|
|
.ks-severity.is-high::before { background: var(--ks-vermilion); }
|
|
.ks-severity.is-medium { color: var(--ks-kinpaku); }
|
|
.ks-severity.is-medium::before { background: var(--ks-kinpaku); }
|
|
.ks-severity.is-low { color: var(--ks-muted); }
|
|
.ks-severity.is-low::before { background: var(--ks-muted); }
|
|
|
|
.ks-audit-row-title {
|
|
color: var(--ks-champagne);
|
|
font-size: 0.96rem;
|
|
font-weight: 400;
|
|
display: block;
|
|
}
|
|
|
|
.ks-audit-row-meta {
|
|
display: block;
|
|
margin-top: 2px;
|
|
color: var(--ks-muted);
|
|
font-size: 0.82rem;
|
|
}
|
|
|
|
.ks-audit-status {
|
|
color: var(--ks-muted);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.7rem;
|
|
letter-spacing: 0.16em;
|
|
text-transform: uppercase;
|
|
}
|
|
.ks-audit-status.is-improved { color: var(--ks-patina); }
|
|
.ks-audit-status.is-ready { color: var(--ks-kinpaku); }
|
|
|
|
/* ============================================================================
|
|
Component grids
|
|
============================================================================ */
|
|
|
|
.ks-component-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
gap: 56px;
|
|
align-items: start;
|
|
}
|
|
|
|
.ks-component-grid-3 {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 48px;
|
|
align-items: start;
|
|
}
|
|
|
|
.ks-component {
|
|
display: grid;
|
|
gap: 16px;
|
|
align-self: start;
|
|
}
|
|
|
|
.ks-component-label {
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.24em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Footer (re-enabled)
|
|
============================================================================ */
|
|
|
|
.ks-footer {
|
|
position: relative;
|
|
border-top: 1px solid var(--ks-rule);
|
|
padding: 80px 56px 56px;
|
|
margin-top: 80px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.ks-footer::after {
|
|
content: "";
|
|
position: absolute;
|
|
right: -2%;
|
|
top: -10%;
|
|
width: 220px;
|
|
height: 140%;
|
|
background: url("/assets/neo-kinpaku/oxidation-edge-accent.png") right center / contain no-repeat;
|
|
opacity: 0.85;
|
|
pointer-events: none;
|
|
filter: saturate(1.1);
|
|
}
|
|
|
|
.ks-footer-inner {
|
|
position: relative;
|
|
z-index: 1;
|
|
max-width: 1320px;
|
|
margin: 0 auto;
|
|
display: grid;
|
|
grid-template-columns: 1.3fr 2fr;
|
|
gap: 64px;
|
|
}
|
|
|
|
.ks-footer-brand .ks-brand { margin-bottom: 22px; }
|
|
|
|
.ks-footer-tagline {
|
|
color: var(--ks-muted);
|
|
max-width: 280px;
|
|
font-size: 0.92rem;
|
|
line-height: 1.55;
|
|
}
|
|
|
|
.ks-footer-links {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 32px;
|
|
}
|
|
|
|
.ks-footer-col h4 {
|
|
margin: 0 0 14px;
|
|
color: var(--ks-kinpaku);
|
|
font-family: var(--ks-mono);
|
|
font-size: 0.66rem;
|
|
letter-spacing: 0.24em;
|
|
text-transform: uppercase;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.ks-footer-col ul {
|
|
list-style: none;
|
|
margin: 0;
|
|
padding: 0;
|
|
display: grid;
|
|
gap: 10px;
|
|
}
|
|
|
|
.ks-footer-col a {
|
|
color: var(--ks-champagne);
|
|
font-size: 0.92rem;
|
|
text-decoration: none;
|
|
transition: color 180ms var(--ks-ease);
|
|
}
|
|
|
|
.ks-footer-col a:hover { color: var(--ks-kinpaku); }
|
|
|
|
.ks-footer-meta {
|
|
max-width: 1320px;
|
|
margin: 56px auto 0;
|
|
padding-top: 22px;
|
|
border-top: 1px solid var(--ks-rule);
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 18px;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
position: relative;
|
|
z-index: 1;
|
|
}
|
|
|
|
.ks-footer-meta small {
|
|
color: var(--ks-mute-deep);
|
|
font-size: 0.78rem;
|
|
}
|
|
|
|
.ks-footer-social {
|
|
display: flex;
|
|
gap: 14px;
|
|
}
|
|
.ks-footer-social a {
|
|
width: 32px;
|
|
height: 32px;
|
|
display: grid;
|
|
place-items: center;
|
|
color: var(--ks-muted);
|
|
border: 1px solid var(--ks-rule);
|
|
border-radius: 2px;
|
|
transition: color 180ms var(--ks-ease), border-color 180ms var(--ks-ease);
|
|
}
|
|
.ks-footer-social a:hover {
|
|
color: var(--ks-kinpaku);
|
|
border-color: var(--ks-kinpaku);
|
|
}
|
|
.ks-footer-social svg { width: 14px; height: 14px; }
|
|
|
|
/* ============================================================================
|
|
Focus states
|
|
============================================================================ */
|
|
|
|
.kinpaku-system-page button:focus-visible,
|
|
.kinpaku-system-page a:focus-visible,
|
|
.kinpaku-system-page input:focus-visible,
|
|
.kinpaku-system-page select:focus-visible {
|
|
outline: 2px solid var(--ks-patina);
|
|
outline-offset: 3px;
|
|
}
|
|
|
|
/* ============================================================================
|
|
Responsive
|
|
============================================================================ */
|
|
|
|
@media (max-width: 1080px) {
|
|
.ks-section { padding: 80px 36px; }
|
|
.ks-footer { padding: 64px 36px 40px; }
|
|
.ks-hero { padding: 28px 36px 0; }
|
|
.ks-category-rail { margin: 0 -36px; grid-template-columns: repeat(3, 1fr); }
|
|
.ks-category-rail a:nth-child(4),
|
|
.ks-category-rail a:nth-child(5) { display: none; }
|
|
|
|
.ks-swatch-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
|
|
.ks-proof-grid { grid-template-columns: 1fr; }
|
|
.ks-component-grid { grid-template-columns: 1fr; gap: 36px; }
|
|
.ks-component-grid-3 { grid-template-columns: repeat(2, 1fr); gap: 32px; }
|
|
.ks-footer-inner { grid-template-columns: 1fr; gap: 40px; }
|
|
.ks-audit-result { padding: 24px; gap: 24px; }
|
|
}
|
|
|
|
@media (max-width: 720px) {
|
|
.ks-section { padding: 64px 24px; }
|
|
.ks-hero { padding: 20px 24px 0; }
|
|
.ks-category-rail { margin: 0 -24px; grid-template-columns: repeat(2, 1fr); }
|
|
.ks-category-rail a:nth-child(3) { display: none; }
|
|
.ks-nav { display: none; }
|
|
.ks-topbar > .ks-nav { display: none; }
|
|
.ks-hero-actions { flex-direction: column; align-items: stretch; }
|
|
.ks-hero-actions .ks-button { width: 100%; }
|
|
.ks-swatch-grid { grid-template-columns: repeat(2, 1fr); }
|
|
.ks-component-grid-3 { grid-template-columns: 1fr; }
|
|
.ks-footer-links { grid-template-columns: 1fr 1fr; }
|
|
.ks-audit-result { grid-template-columns: 1fr; gap: 24px; padding: 24px 0; }
|
|
.ks-type-row { grid-template-columns: 1fr; gap: 12px; }
|
|
}
|
|
|
|
@media (prefers-reduced-motion: reduce) {
|
|
.kinpaku-system-page *,
|
|
.kinpaku-system-page *::before,
|
|
.kinpaku-system-page *::after {
|
|
animation-duration: 0.01ms !important;
|
|
transition-duration: 0.01ms !important;
|
|
}
|
|
}
|