Files
klarbild-demo/src/styles/site.css
T
Claude 880644e026 German page, and a section for the image module
/ and /de/ are now two pages from one shared component and one copy file, with
hreflang between them and a language button in the header. Separate URLs rather
than a runtime switch: each language is linkable and indexable, and the page
still works without JavaScript. The sheet playground takes its labels from the
page, so its readout says "29,7 cm" in German and "29.7 cm" in English.

New section for the `ai` module, because the page so far read as if Klarbild
were print-only. It says plainly what the module costs and that the endpoint is
configurable, and it carries a preset builder: pick tasks and a target size,
see the exact pixels and the recipe that gets saved. It composes; it does not
generate. A generator here would need a key on a public page and would show a
picture from a model rather than anything about Klarbild — the part worth
showing is the recipe.

The target pixels come from engine/format.ts, copied verbatim from the
application like the layout files.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nh4A79bbqT9dcd2inzYUdg
2026-09-15 15:40:07 +00:00

248 lines
15 KiB
CSS

/* Klarbild demo site — the product's own tokens, one accent, warm paper. */
:root {
--measure: 62ch;
--gutter: clamp(20px, 5vw, 64px);
--wide: 1240px;
--bleed: oklch(88% 0.012 150);
--cellfill: oklch(93.5% 0.012 150);
--cellink: oklch(58% 0.035 158);
}
body {
background:
radial-gradient(70rem 40rem at 82% -10%, oklch(45% 0.23 267 / 0.05), transparent 60%),
var(--paper);
background-attachment: fixed;
}
/* Paper grain. Fixed and pointer-transparent so it never repaints on scroll. */
body::after {
content: '';
position: fixed;
inset: 0;
pointer-events: none;
z-index: 1;
opacity: 0.32;
mix-blend-mode: multiply;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.28'/%3E%3C/svg%3E");
}
.shell { width: min(100% - var(--gutter) * 2, var(--wide)); margin-inline: auto; }
/* The top bar is sticky, so anything jumped to needs room above it. */
:target, section[id], #try { scroll-margin-top: 78px; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
.prose { max-width: var(--measure); }
h1, h2, h3 { font-family: var(--font-display); letter-spacing: -0.03em; line-height: 1.02; margin: 0; }
h1 { font-size: clamp(2.6rem, 7vw, 5.1rem); font-weight: 700; }
h2 { font-size: clamp(1.7rem, 3.6vw, 2.7rem); font-weight: 700; }
h3 { font-size: 1.05rem; font-weight: 700; letter-spacing: -0.01em; }
p { margin: 0 0 1em; }
.lead { font-size: clamp(1.05rem, 1.8vw, 1.28rem); color: var(--ink-soft); line-height: 1.6; }
.kicker { font-family: var(--font-mono); font-size: 10.5px; letter-spacing: 0.2em;
text-transform: uppercase; color: var(--ink-soft); display: block; margin-bottom: 14px; }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
/* ------------------------------------------------------------------- header */
.top {
position: sticky; top: 0; z-index: 30;
backdrop-filter: saturate(1.3) blur(10px);
background: color-mix(in oklab, var(--paper) 82%, transparent);
border-bottom: 1px solid var(--line);
}
.top-in { display: flex; align-items: center; gap: 18px; padding: 13px 0;
padding-top: calc(13px + env(safe-area-inset-top, 0px)); }
.brand { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-display);
font-weight: 700; font-size: 1.14rem; color: var(--ink); text-decoration: none; letter-spacing: -0.02em; }
.top nav { margin-left: auto; display: flex; align-items: center; gap: 6px; }
.top nav a { color: var(--ink-soft); text-decoration: none; font-size: 0.88rem;
padding: 7px 11px; border-radius: 999px; }
.top nav a:hover { color: var(--ink); background: var(--card); }
.top nav a.cta { color: #fff; background: var(--accent); font-weight: 600; }
.top nav a.cta:hover { background: var(--accent-2); color: #fff; }
@media (max-width: 720px) { .top nav a.hide-s { display: none; } }
/* --------------------------------------------------------------------- hero */
.hero { padding: clamp(48px, 9vw, 108px) 0 clamp(36px, 6vw, 64px); position: relative; z-index: 2; }
.hero-grid { display: grid; gap: clamp(28px, 5vw, 56px); align-items: end;
grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .hero-grid { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); } }
.hero h1 span { color: var(--accent); }
.hero .lead { margin-top: 22px; max-width: 46ch; }
.hero-side { border-left: 1px solid var(--line); padding-left: clamp(18px, 3vw, 30px); }
@media (max-width: 899px) { .hero-side { border-left: 0; padding-left: 0; border-top: 1px solid var(--line); padding-top: 22px; } }
.hero-side dl { display: grid; grid-template-columns: auto 1fr; gap: 9px 16px; margin: 0; }
.hero-side dt { font-family: var(--font-mono); font-size: 1.05rem; font-weight: 700;
font-variant-numeric: tabular-nums; color: var(--ink); }
.hero-side dd { margin: 0; font-size: 0.86rem; color: var(--ink-soft); align-self: center; }
.btnrow { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 30px; }
.btn { display: inline-flex; align-items: center; gap: 8px; border: 1px solid var(--line);
background: var(--card); color: var(--ink); text-decoration: none; font-weight: 600;
font-size: 0.93rem; padding: 12px 18px; border-radius: var(--radius); cursor: pointer;
font-family: inherit; transition: transform .12s cubic-bezier(.16,1,.3,1), background .16s, border-color .16s; }
.btn:hover { border-color: var(--ink-soft); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff;
box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.16); }
.btn.primary:hover { background: var(--accent-2); border-color: var(--accent-2); }
.btn[disabled] { opacity: .55; cursor: progress; }
/* --------------------------------------------------------------- playground */
.pg { position: relative; z-index: 2; padding-bottom: clamp(40px, 7vw, 88px); }
.pg-shell { background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
box-shadow: 0 18px 50px -34px oklch(21% 0.01 95 / 0.5); overflow: hidden; }
.pg-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px 18px;
padding: 15px 18px; border-bottom: 1px solid var(--line); }
.pg-head h2 { font-size: 1.05rem; }
.pg-head .fine { font-size: 0.82rem; color: var(--ink-soft); margin-left: auto; }
.pg-body { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 880px) { .pg-body { grid-template-columns: minmax(300px, 380px) minmax(0, 1fr); } }
.pg-controls { padding: 20px 18px; display: grid; gap: 17px; align-content: start; }
@media (min-width: 880px) { .pg-controls { border-right: 1px solid var(--line); } }
.field { display: grid; gap: 6px; }
.field > label { font-family: var(--font-mono); font-size: 10px; letter-spacing: .16em;
text-transform: uppercase; color: var(--ink-soft); }
select, input[type=number] { font-family: inherit; font-size: 0.94rem; color: var(--ink);
background: var(--paper); border: 1px solid var(--line); border-radius: var(--radius-sm);
padding: 9px 10px; width: 100%; }
input[type=range] { width: 100%; accent-color: var(--accent); }
.seg { display: flex; gap: 0; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.seg button { flex: 1; font-family: inherit; font-size: 0.85rem; padding: 9px 6px; border: 0;
background: var(--paper); color: var(--ink-soft); cursor: pointer; border-right: 1px solid var(--line); }
.seg button:last-child { border-right: 0; }
.seg button[aria-pressed=true] { background: var(--accent-bg); color: var(--accent); font-weight: 600; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.slider-head { display: flex; justify-content: space-between; align-items: baseline; }
.slider-head span { font-family: var(--font-mono); font-size: 0.78rem; color: var(--ink); }
.toggle { display: flex; align-items: center; gap: 9px; font-size: 0.88rem; color: var(--ink-soft); }
.toggle button { width: 38px; height: 22px; border-radius: 999px; border: 1px solid var(--line);
background: var(--paper); position: relative; cursor: pointer; padding: 0; }
.toggle button::after { content: ''; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
border-radius: 50%; background: var(--mark); transition: transform .16s cubic-bezier(.16,1,.3,1), background .16s; }
.toggle button[aria-pressed=true] { border-color: var(--accent); background: var(--accent-bg); }
.toggle button[aria-pressed=true]::after { transform: translateX(16px); background: var(--accent); }
.pg-stage { padding: 22px 18px 26px; display: grid; gap: 16px; align-content: start;
background: repeating-linear-gradient(45deg, transparent 0 11px, oklch(21% 0.01 95 / 0.015) 11px 22px); }
.stage-sheet { display: grid; place-items: center; }
#sheet { width: auto; max-width: 100%; max-height: min(58vh, 520px);
filter: drop-shadow(0 10px 26px oklch(21% 0.01 95 / 0.16)); background: #fff; }
#sheet .cell { animation: pop .34s cubic-bezier(.16,1,.3,1) backwards;
animation-delay: calc(var(--i) * 22ms); }
@keyframes pop { from { opacity: 0; transform: scale(.965); } }
@media (prefers-reduced-motion: reduce) { #sheet .cell { animation: none; } }
.readout { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1px;
background: var(--line); border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
@media (min-width: 560px) { .readout { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.readout div { background: var(--card); padding: 10px 12px; }
.readout dt { font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .15em;
text-transform: uppercase; color: var(--ink-soft); margin-bottom: 3px; }
.readout dd { margin: 0; font-family: var(--font-mono); font-size: 0.95rem; font-weight: 700;
font-variant-numeric: tabular-nums; }
.note { font-size: 0.88rem; padding: 10px 12px; border-left: 2px solid var(--mark);
background: var(--paper); color: var(--ink-soft); }
.note[data-tone=ok] { border-left-color: var(--ok); }
.note[data-tone=warn] { border-left-color: var(--warn); color: var(--ink); }
.pg-foot { display: flex; flex-wrap: wrap; align-items: center; gap: 12px;
padding: 14px 18px; border-top: 1px solid var(--line); }
.pg-foot p { margin: 0; font-size: 0.82rem; color: var(--ink-soft); max-width: 52ch; }
/* ----------------------------------------------------------------- sections */
section { position: relative; z-index: 2; padding: clamp(46px, 8vw, 96px) 0; }
section + section { border-top: 1px solid var(--line); }
.zig { display: grid; gap: clamp(24px, 4vw, 52px); align-items: center;
grid-template-columns: minmax(0, 1fr); }
@media (min-width: 880px) { .zig { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
@media (min-width: 880px) { .zig.flip > :first-child { order: 2; } }
.zig figure { margin: 0; border: 1px solid var(--line); border-radius: var(--radius);
overflow: hidden; background: var(--card); box-shadow: 0 16px 44px -34px oklch(21% 0.01 95 / 0.55); }
.zig figure img { display: block; width: 100%; height: auto; }
.zig figcaption { font-size: 0.8rem; color: var(--ink-soft); padding: 9px 12px; border-top: 1px solid var(--line); }
.facts { display: grid; gap: 0; margin-top: 30px; border-top: 1px solid var(--line); }
.facts > div { display: grid; gap: 4px; padding: 16px 0; border-bottom: 1px solid var(--line); }
@media (min-width: 680px) { .facts > div { grid-template-columns: 13rem minmax(0, 1fr); gap: 20px; align-items: baseline; } }
.facts h3 { color: var(--ink); }
.facts p { margin: 0; color: var(--ink-soft); font-size: 0.94rem; }
/* Modules: a list that reads as a switchboard, not three equal cards. */
.mods { display: grid; gap: 0; border-top: 1px solid var(--line); margin-top: 32px; }
.mod { display: grid; gap: 4px 18px; padding: 15px 0; border-bottom: 1px solid var(--line);
grid-template-columns: minmax(0, 1fr); }
@media (min-width: 760px) { .mod { grid-template-columns: 9.5rem minmax(0, 1fr) 15rem; align-items: baseline; } }
.mod code { font-family: var(--font-mono); font-size: 0.86rem; color: var(--accent); }
.mod.core code { color: var(--ink); }
.mod p { margin: 0; font-size: 0.94rem; }
.mod .need { font-size: 0.83rem; color: var(--ink-soft); }
.mod.core { background: linear-gradient(90deg, var(--accent-bg), transparent 60%); }
pre { background: var(--ink); color: oklch(94% 0.01 95); font-family: var(--font-mono);
font-size: 0.83rem; line-height: 1.7; padding: 16px 18px; border-radius: var(--radius);
overflow-x: auto; margin: 0; }
pre .c { color: oklch(66% 0.02 95); }
code { font-family: var(--font-mono); font-size: 0.9em; }
.split-code { display: grid; gap: clamp(22px, 4vw, 44px); grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 880px) { .split-code { grid-template-columns: minmax(0, 0.95fr) minmax(0, 1.05fr); } }
footer { position: relative; z-index: 2; border-top: 1px solid var(--line);
padding: 40px 0 calc(48px + env(safe-area-inset-bottom, 0px)); }
.foot-in { display: flex; flex-wrap: wrap; gap: 14px 28px; align-items: baseline; }
footer a { color: var(--ink-soft); text-decoration: none; font-size: 0.88rem; }
footer a:hover { color: var(--accent); }
footer .fine { font-size: 0.8rem; color: var(--ink-soft); margin-left: auto; }
@media (max-width: 620px) { footer .fine { margin-left: 0; width: 100%; } }
/* ------------------------------------------------- language switch & nav bits */
.top nav a.langswitch { font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: .08em;
border: 1px solid var(--line); padding: 6px 9px; border-radius: 999px; line-height: 1; }
.top nav a.langswitch:hover { color: var(--accent); border-color: var(--accent); background: transparent; }
@media (max-width: 980px) { .top nav a.hide-m { display: none; } }
/* ------------------------------------------------------------ preset builder */
.recipe { margin-top: clamp(28px, 4vw, 48px); }
.recipe-body { display: grid; grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .recipe-body { grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr); } }
.recipe-controls { padding: 20px 18px; display: grid; gap: 18px; align-content: start; }
@media (min-width: 900px) { .recipe-controls { border-right: 1px solid var(--line); } }
.recipe-out { padding: 20px 18px; display: grid; gap: 14px; align-content: start;
background: repeating-linear-gradient(45deg, transparent 0 11px, oklch(21% 0.01 95 / 0.015) 11px 22px); }
.chips { display: flex; flex-wrap: wrap; gap: 6px; }
.chips button { font-family: inherit; font-size: 0.82rem; padding: 7px 11px; cursor: pointer;
border: 1px solid var(--line); border-radius: 999px; background: var(--paper); color: var(--ink-soft);
transition: border-color .15s, color .15s, background .15s; }
.chips button:hover { color: var(--ink); border-color: var(--ink-soft); }
.chips button[aria-pressed=true] { background: var(--accent-bg); border-color: var(--accent);
color: var(--accent); font-weight: 600; }
.tasklist { display: grid; gap: 6px; }
@media (min-width: 560px) { .tasklist { grid-template-columns: 1fr 1fr; } }
.tasklist button { display: grid; gap: 2px; text-align: left; font-family: inherit; cursor: pointer;
border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--paper);
padding: 10px 12px; transition: border-color .15s, background .15s; }
.tasklist button b { font-size: 0.92rem; color: var(--ink); font-weight: 600; }
.tasklist button em { font-style: normal; font-size: 0.78rem; color: var(--ink-soft); line-height: 1.4; }
.tasklist button[aria-pressed=true] { background: var(--accent-bg); border-color: var(--accent); }
.tasklist button[aria-pressed=true] b { color: var(--accent); }
.tasklist button[aria-pressed=true] b::after { content: ' ✓'; }
.tasklist button:disabled { opacity: .45; cursor: not-allowed; }
.readout.single { grid-template-columns: minmax(0, 1fr); }
.recipe-out pre { font-size: 0.78rem; line-height: 1.65; max-height: 280px; }
.mod-after { display: grid; gap: 22px; margin-top: 26px; align-items: start; }
@media (min-width: 880px) { .mod-after { grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr); gap: 40px; } }
.stackline { font-size: .84rem; color: var(--ink-soft); margin-top: 14px; }