site, branding: skeuomorphic marks, and the new Niveus components

The marks are now drawn the way Niveus draws its keys: one light from the
upper left, gloss on the faces that catch it, a specular line on the edges
that face it, and soft contact shadows.

- Shift: shaded slabs, each casting onto the one below. shift-mask.svg is
  untouched, so the kernel's logo.h coverage mask is unchanged.
- Uberblock: bevelled slots in a groove; the newest slot and the root glow.
- USB stick: moulded body, steel connector, a lit activity LED.
- Pride flag: cloth folds and a hem over the flag's own colours.

The pages use the components the new Niveus added: both terminals are
.nv-window frames, the origin and first-boot sequences are .nv-steps, the
numbers are a .nv-stat-group, and each feature card has an .nv-tile glyph.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
This commit is contained in:
Nexoniarz 2026-10-23 15:17:34 +02:00
commit c9790df04c
11 changed files with 623 additions and 321 deletions

View file

@ -1,106 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 28 18"
width="28"
height="18"
role="img"
aria-labelledby="pride-title"
version="1.1"
id="svg10"
sodipodi:docname="pride.svg"
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs10" />
<sodipodi:namedview
id="namedview10"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="28.814601"
inkscape:cx="15.773253"
inkscape:cy="10.706378"
inkscape:window-width="1920"
inkscape:window-height="1056"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg10" />
<title
id="pride-title">Progress Pride flag</title>
<desc
id="desc1">The six-stripe rainbow with the Progress chevron: white, pink and light
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 18" width="28" height="18"
role="img" aria-labelledby="pride-title">
<title id="pride-title">Progress Pride flag</title>
<desc>The six-stripe rainbow with the Progress chevron: white, pink and light
blue for trans people, brown and black for queer people of colour and for
those lost to AIDS. It sits in the top bar every day of the year, which is
the whole point of it.</desc>
the whole point of it.
Drawn as cloth rather than as a swatch, to match the rest of the site: two
soft folds run down it, light from the upper left catches the crest of each,
and the edge facing the light carries a thin highlight. The colours under the
shading are the flag's own and are not adjusted.</desc>
<defs>
<clipPath id="cloth"><rect width="28" height="18" rx="1.6"/></clipPath>
<!-- the folds: crests lighter, troughs darker, across the width -->
<linearGradient id="folds" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.22"/>
<stop offset="0.18" stop-color="#000000" stop-opacity="0.10"/>
<stop offset="0.38" stop-color="#FFFFFF" stop-opacity="0.18"/>
<stop offset="0.60" stop-color="#000000" stop-opacity="0.16"/>
<stop offset="0.80" stop-color="#FFFFFF" stop-opacity="0.12"/>
<stop offset="1" stop-color="#000000" stop-opacity="0.18"/>
</linearGradient>
<!-- light from above, shade at the hem -->
<linearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.16"/>
<stop offset="0.5" stop-color="#FFFFFF" stop-opacity="0"/>
<stop offset="1" stop-color="#000000" stop-opacity="0.18"/>
</linearGradient>
</defs>
<g clip-path="url(#cloth)">
<!-- the six -->
<rect
width="28"
height="3"
y="0"
fill="#E40303"
id="rect1" />
<rect
width="28"
height="3"
y="3"
fill="#FF8C00"
id="rect2" />
<rect
width="28"
height="3"
y="6"
fill="#FFED00"
id="rect3" />
<rect
width="28"
height="3"
y="9"
fill="#008026"
id="rect4" />
<rect
width="28"
height="3"
y="12"
fill="#24408E"
id="rect5" />
<rect
width="28"
height="3"
y="15"
fill="#732982"
id="rect6" />
<!-- the chevron: nested, outermost first, so each one leaves a band -->
<polygon
points="0,18 13,9 0,0 "
fill="#ffffff"
id="polygon6"
transform="scale(0.97864331,1)" />
<polygon
points="11,9 0,0 0,18 "
fill="#ffafc8"
id="polygon7"
transform="matrix(0.98738014,0,0,0.98091343,0,0.17177914)" />
<polygon
points="0,18 9,9 0,0 "
fill="#74d7ee"
id="polygon8"
transform="matrix(1,0,0,0.96455351,0,0.3190184)" />
<polygon
points="0,18 7,9 0,0 "
fill="#613915"
id="polygon9"
transform="matrix(1,0,0,0.92365372,0,0.68711656)" />
<polygon
points="5,9 0,0 0,18 "
fill="#000000"
id="polygon10"
transform="matrix(1.0624683,0,0,0.85276074,0,1.3251534)" />
<rect width="28" height="3" y="0" fill="#E40303"/>
<rect width="28" height="3" y="3" fill="#FF8C00"/>
<rect width="28" height="3" y="6" fill="#FFED00"/>
<rect width="28" height="3" y="9" fill="#008026"/>
<rect width="28" height="3" y="12" fill="#24408E"/>
<rect width="28" height="3" y="15" fill="#732982"/>
<!-- the chevron, outermost first -->
<polygon points="0,18 13,9 0,0" fill="#FFFFFF"/>
<polygon points="0,18 11,9 0,0" fill="#FFAFC8"/>
<polygon points="0,18 9,9 0,0" fill="#74D7EE"/>
<polygon points="0,18 7,9 0,0" fill="#613915"/>
<polygon points="0,18 5,9 0,0" fill="#000000"/>
<rect width="28" height="18" fill="url(#folds)"/>
<rect width="28" height="18" fill="url(#sky)"/>
</g>
<!-- the hem: lit along the top and left, shaded along the bottom and right -->
<rect x="0.25" y="0.25" width="27.5" height="17.5" rx="1.45" fill="none"
stroke="#000000" stroke-opacity="0.35" stroke-width="0.5"/>
<path d="M0.6 16.6 V1.8 a1.2 1.2 0 0 1 1.2 -1.2 H26.2" fill="none"
stroke="#FFFFFF" stroke-opacity="0.45" stroke-width="0.5" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Before After
Before After

View file

@ -8,20 +8,101 @@
without it the slab has no thickness where it is widest, and the corner reads
as a hole rather than an edge.
Drawn the way Niveus draws a key: light falls from the upper left, so every
top face is brightest at its far-left corner and every edge that faces the
light carries a thin specular line. The front faces are lit from above and
darken towards the ground; the end walls face away and are darkest. Each slab
casts a soft shadow on the one below it, which is what makes the stack read
as three objects rather than three stripes.
Geometry is shared with "shift-mask.svg"; see that file.</desc>
<defs>
<!-- top faces: lit corner to far corner -->
<linearGradient id="t1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#A48CFF"/>
<stop offset="0.55" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#6A48F0"/>
</linearGradient>
<linearGradient id="t2" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#8064E6"/>
<stop offset="0.55" stop-color="#5B44C4"/>
<stop offset="1" stop-color="#4E39AE"/>
</linearGradient>
<linearGradient id="t3" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#5A48A8"/>
<stop offset="0.55" stop-color="#3C2E85"/>
<stop offset="1" stop-color="#332772"/>
</linearGradient>
<!-- front faces: lit at the top edge, falling into shade -->
<linearGradient id="f1" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#6E50E8"/>
<stop offset="1" stop-color="#4E35BC"/>
</linearGradient>
<linearGradient id="f2" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#4E3AAE"/>
<stop offset="1" stop-color="#372887"/>
</linearGradient>
<linearGradient id="f3" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#342874"/>
<stop offset="1" stop-color="#231A52"/>
</linearGradient>
<!-- end walls: facing away from the light -->
<linearGradient id="w1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#4F36B4"/>
<stop offset="1" stop-color="#3A2690"/>
</linearGradient>
<linearGradient id="w2" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#3A2A86"/>
<stop offset="1" stop-color="#2B1F68"/>
</linearGradient>
<linearGradient id="w3" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#261C56"/>
<stop offset="1" stop-color="#1A133E"/>
</linearGradient>
<!-- the gloss across each top face, strongest at its back edge -->
<linearGradient id="gloss" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.38"/>
<stop offset="0.45" stop-color="#FFFFFF" stop-opacity="0.08"/>
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/>
</linearGradient>
<filter id="soft" x="-20%" y="-40%" width="140%" height="180%">
<feGaussianBlur stdDeviation="4"/>
</filter>
</defs>
<!-- contact shadows, each cast down and to the right of its slab -->
<path fill="#000" opacity="0.35" filter="url(#soft)" d="M58 138 L160 138 L132 170 L28 170 Z"/>
<path fill="#000" opacity="0.30" filter="url(#soft)" d="M76 96 L178 96 L150 128 L46 128 Z"/>
<path fill="#000" opacity="0.26" filter="url(#soft)" d="M94 54 L196 54 L168 86 L64 86 Z"/>
<!-- bottom slab -->
<path fill="#3C2E85" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="#31256E" d="M24 156 L128 156 L128 167 L24 167 Z"/>
<path fill="#291F5C" d="M158 126 L158 137 L128 167 L128 156 Z"/>
<path fill="url(#t3)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="url(#gloss)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="url(#f3)" d="M24 156 L128 156 L128 167 L24 167 Z"/>
<path fill="url(#w3)" d="M158 126 L158 137 L128 167 L128 156 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.35" stroke-width="1.2"
stroke-linecap="round" d="M24.6 155.4 L54.4 126.6 L157 126.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.16" stroke-width="1"
d="M24 156.5 L128 156.5"/>
<!-- middle slab -->
<path fill="#5B44C4" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="#4B37A6" d="M42 114 L146 114 L146 125 L42 125 Z"/>
<path fill="#3F2D8C" d="M176 84 L176 95 L146 125 L146 114 Z"/>
<path fill="url(#t2)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="url(#gloss)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="url(#f2)" d="M42 114 L146 114 L146 125 L42 125 Z"/>
<path fill="url(#w2)" d="M176 84 L176 95 L146 125 L146 114 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.42" stroke-width="1.2"
stroke-linecap="round" d="M42.6 113.4 L72.4 84.6 L175 84.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.18" stroke-width="1"
d="M42 114.5 L146 114.5"/>
<!-- top slab -->
<path fill="#7C5CFF" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="#6949E0" d="M60 72 L164 72 L164 83 L60 83 Z"/>
<path fill="#5B3FC9" d="M194 42 L194 53 L164 83 L164 72 Z"/>
<path fill="url(#t1)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="url(#gloss)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="url(#f1)" d="M60 72 L164 72 L164 83 L60 83 Z"/>
<path fill="url(#w1)" d="M194 42 L194 53 L164 83 L164 72 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.55" stroke-width="1.2"
stroke-linecap="round" d="M60.6 71.4 L90.4 42.6 L193 42.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.22" stroke-width="1"
d="M60 72.5 L164 72.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Before After
Before After

View file

@ -20,10 +20,66 @@
survives include/gfx/logo.h, which is a single coverage channel and keeps no
colour at all.
Drawn as Niveus draws a dial: the slots are raised keys set into a groove
cut into the surface, bevelled by one light from the upper left, and the
newest slot and the root are lit from inside. The geometry is unchanged.
Stands alone, with no reference to SchOS, as projects/schfs-linux/README.md
requires.</desc>
<g fill="#3C2E85">
<defs>
<!-- one light for the whole dial, so every slot is lit from the same side -->
<linearGradient id="slot" gradientUnits="userSpaceOnUse" x1="20" y1="20" x2="180" y2="180">
<stop offset="0" stop-color="#5A47B0"/>
<stop offset="0.5" stop-color="#3C2E85"/>
<stop offset="1" stop-color="#2A2066"/>
</linearGradient>
<linearGradient id="lit" gradientUnits="userSpaceOnUse" x1="120" y1="10" x2="160" y2="56">
<stop offset="0" stop-color="#B09CFF"/>
<stop offset="0.5" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#5A3BE0"/>
</linearGradient>
<radialGradient id="root" cx="0.38" cy="0.34" r="0.7">
<stop offset="0" stop-color="#E4DCFF"/>
<stop offset="0.3" stop-color="#9F86FF"/>
<stop offset="0.75" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#4E32C8"/>
</radialGradient>
<radialGradient id="groove" cx="0.5" cy="0.5" r="0.5">
<stop offset="0.5" stop-color="#0E0B1E" stop-opacity="0"/>
<stop offset="0.62" stop-color="#0E0B1E" stop-opacity="0.55"/>
<stop offset="0.92" stop-color="#0E0B1E" stop-opacity="0.55"/>
<stop offset="1" stop-color="#0E0B1E" stop-opacity="0"/>
</radialGradient>
<radialGradient id="halo" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" stop-color="#9F86FF" stop-opacity="0.55"/>
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
</radialGradient>
<!-- The bevel: the shape's own alpha, blurred into a height map and lit
from the upper left, added back over the fill. -->
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
<feGaussianBlur in="SourceAlpha" stdDeviation="1.6" result="h"/>
<feSpecularLighting in="h" surfaceScale="3" specularConstant="0.85"
specularExponent="16" lighting-color="#FFFFFF" result="s">
<feDistantLight azimuth="225" elevation="40"/>
</feSpecularLighting>
<feComposite in="s" in2="SourceAlpha" operator="in" result="sa"/>
<feComposite in="SourceGraphic" in2="sa" operator="arithmetic" k2="1" k3="0.55"/>
</filter>
<filter id="drop" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="2.5"/>
<feOffset dx="1.5" dy="2.5" result="o"/>
<feComponentTransfer><feFuncA type="linear" slope="0.5"/></feComponentTransfer>
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- the groove the slots sit in -->
<circle cx="100" cy="100" r="86" fill="url(#groove)"/>
<g filter="url(#drop)">
<g fill="url(#slot)" filter="url(#bevel)">
<path d="M85.93 20.23 A81.00 81.00 0 0 1 114.07 20.23 L110.25 41.90 A59.00 59.00 0 0 0 89.75 41.90 Z"/>
<path d="M162.05 47.93 A81.00 81.00 0 0 1 176.12 72.30 L155.44 79.82 A59.00 59.00 0 0 0 145.20 62.08 Z"/>
<path d="M179.77 85.93 A81.00 81.00 0 0 1 179.77 114.07 L158.10 110.25 A59.00 59.00 0 0 0 158.10 89.75 Z"/>
@ -36,9 +92,16 @@
<path d="M23.88 72.30 A81.00 81.00 0 0 1 37.95 47.93 L54.80 62.08 A59.00 59.00 0 0 0 44.56 79.82 Z"/>
<path d="M47.93 37.95 A81.00 81.00 0 0 1 72.30 23.88 L79.82 44.56 A59.00 59.00 0 0 0 62.08 54.80 Z"/>
</g>
<g fill="#7C5CFF">
<path d="M132.15 11.67 A94.00 94.00 0 0 1 160.42 27.99 L137.92 54.80 A59.00 59.00 0 0 0 120.18 44.56 Z"/>
<circle cx="100" cy="100" r="20"/>
</g>
<!-- the newest slot and the root it names, lit from inside -->
<circle cx="141" cy="36" r="32" fill="url(#halo)"/>
<circle cx="100" cy="100" r="34" fill="url(#halo)"/>
<g filter="url(#drop)">
<g filter="url(#bevel)">
<path fill="url(#lit)" d="M132.15 11.67 A94.00 94.00 0 0 1 160.42 27.99 L137.92 54.80 A59.00 59.00 0 0 0 120.18 44.56 Z"/>
<circle cx="100" cy="100" r="20" fill="url(#root)"/>
</g>
</g>
<ellipse cx="93" cy="92" rx="6.5" ry="4" fill="#FFFFFF" opacity="0.55"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After

View file

@ -4,24 +4,87 @@
no optical drive in the plan -- the stick is the machine's second disk, and on
a Chromebox it is the only one that matters.
Drawn to the same rule as the other marks here: two tones, geometry only, and
the accent spent in exactly one place. That place is the activity light,
because it is the part of a USB stick that tells you something is happening --
the same job the accent does everywhere else in this palette.
Drawn as an object, the way Niveus draws its controls: a moulded body lit from
the upper left, with a soft rim of light along the edges that face it and a
contact shadow on the ground; a brushed-steel connector whose two contact
windows are cut into it rather than painted on. The accent is still spent in
exactly one place, the activity light -- the part of a USB stick that tells
you something is happening -- and here it glows.</desc>
The connector's two contact windows are real holes (fill-rule evenodd) rather
than shapes filled with the background colour, so the mark survives being put
on a surface that is not the page background.</desc>
<defs>
<linearGradient id="body" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#5B48B8"/>
<stop offset="0.5" stop-color="#3E2F8C"/>
<stop offset="1" stop-color="#2A1F66"/>
</linearGradient>
<linearGradient id="bodygloss" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.30"/>
<stop offset="0.28" stop-color="#FFFFFF" stop-opacity="0.06"/>
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/>
</linearGradient>
<linearGradient id="collar" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#4A3AA0"/>
<stop offset="1" stop-color="#2E2270"/>
</linearGradient>
<linearGradient id="steel" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#9A9AAE"/>
<stop offset="0.25" stop-color="#E9E9F2"/>
<stop offset="0.5" stop-color="#B9B9C9"/>
<stop offset="0.8" stop-color="#D8D8E4"/>
<stop offset="1" stop-color="#85859A"/>
</linearGradient>
<linearGradient id="hole" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#1A1830"/>
<stop offset="1" stop-color="#3A3852"/>
</linearGradient>
<radialGradient id="led" cx="0.4" cy="0.35" r="0.65">
<stop offset="0" stop-color="#FFFFFF"/>
<stop offset="0.25" stop-color="#C9B9FF"/>
<stop offset="0.7" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#5236D6"/>
</radialGradient>
<radialGradient id="ledglow" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" stop-color="#9F86FF" stop-opacity="0.75"/>
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
</radialGradient>
<filter id="soft" x="-30%" y="-30%" width="160%" height="160%">
<feGaussianBlur stdDeviation="5"/>
</filter>
</defs>
<g fill="#3C2E85">
<path fill-rule="evenodd" d="M70 14 h60 v58 h-60 Z
M82 30 h13 v26 h-13 Z
M105 30 h13 v26 h-13 Z"/>
<rect x="62" y="72" width="76" height="15" rx="3"/>
<rect x="54" y="87" width="92" height="99" rx="12"/>
</g>
<!-- the shadow it casts -->
<ellipse cx="104" cy="186" rx="44" ry="7" fill="#000" opacity="0.4" filter="url(#soft)"/>
<g fill="#7C5CFF">
<circle cx="100" cy="162" r="9"/>
</g>
<!-- connector: steel shell with two windows cut through it -->
<path fill="url(#steel)" fill-rule="evenodd"
d="M70 18 a4 4 0 0 1 4 -4 h52 a4 4 0 0 1 4 4 v44 h-60 Z
M82 30 h10 v14 h-10 Z M108 30 h10 v14 h-10 Z"/>
<path fill="url(#hole)" d="M82 30 h10 v14 h-10 Z M108 30 h10 v14 h-10 Z" opacity="0.9"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.7" stroke-width="1"
d="M71 62 V18 a3 3 0 0 1 3 -3 h52"/>
<!-- collar where the shell meets the body -->
<rect x="62" y="56" width="76" height="14" rx="3" fill="url(#collar)"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.25" stroke-width="1"
d="M63 69 V59 a2.5 2.5 0 0 1 2.5 -2.5 H135"/>
<!-- the body -->
<rect x="54" y="64" width="92" height="116" rx="16" fill="url(#body)"/>
<rect x="54" y="64" width="92" height="116" rx="16" fill="url(#bodygloss)"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.35" stroke-width="1.4"
stroke-linecap="round" d="M55 170 V80 a15 15 0 0 1 15 -15 h60"/>
<path fill="none" stroke="#000" stroke-opacity="0.35" stroke-width="1.4"
stroke-linecap="round" d="M145 80 v84 a15 15 0 0 1 -15 15 h-60"/>
<!-- a moulded grip: two shallow grooves -->
<path fill="none" stroke="#1E1650" stroke-opacity="0.8" stroke-width="2"
stroke-linecap="round" d="M84 96 h32 M84 106 h32"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.18" stroke-width="1.2"
stroke-linecap="round" d="M84 98.2 h32 M84 108.2 h32"/>
<!-- the activity light, lit -->
<circle cx="100" cy="150" r="22" fill="url(#ledglow)"/>
<circle cx="100" cy="150" r="9" fill="#1C1448"/>
<circle cx="100" cy="150" r="7" fill="url(#led)"/>
<ellipse cx="97.5" cy="147" rx="2.6" ry="1.8" fill="#FFFFFF" opacity="0.85"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Before After
Before After

View file

@ -90,20 +90,14 @@
/* --- The console ----------------------------------------------------------- */
/*
A terminal is a recess, not a card that happens to hold monospace: the
material says "this is a window into the machine" before the text does.
A terminal is a window into the machine, so it is drawn as one: a solid
.nv-window whose body is a recess the log is typed into. The traffic lights
are decoration here -- nothing on this page can be closed -- so they are
spans, hidden from assistive tech, rather than buttons that do nothing.
*/
.console {
overflow: hidden;
}
.console__bar {
display: flex;
align-items: center;
gap: var(--nv-space-3);
padding: var(--nv-space-2) var(--nv-space-3);
border-block-end: var(--nv-border-width) solid var(--nv-color-border-subtle);
min-inline-size: 0;
}
.console__log {
@ -118,7 +112,7 @@
}
/* The cursor the boot log types behind. */
.console__log::after {
#bootlog::after {
content: "";
display: inline-block;
inline-size: 0.6em;
@ -128,50 +122,38 @@
animation: console-blink 1.1s steps(2, start) infinite;
}
/* Only the boot log types; a finished transcript is as tall as it is. */
.console__log:not(#bootlog) { min-block-size: 0; }
@keyframes console-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
.console__log::after { animation: none; }
#bootlog::after { animation: none; }
}
/* --- Origin, as a timeline -------------------------------------------------- */
/* --- Origin, as steps ------------------------------------------------------- */
/*
The rail is not decoration: these steps happened in this order, and the
order is the claim the section makes. A grid would lose it.
order is the claim the section makes. A grid would lose it. .nv-steps cuts
the rail into the surface and lights what is done; all this adds is the
measure, because a step is a paragraph and not a label.
*/
.timeline {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: var(--nv-space-8);
border-inline-start: var(--nv-border-width) solid var(--nv-color-border);
padding-inline-start: var(--nv-space-6);
}
.timeline__step {
display: flex;
flex-direction: column;
gap: var(--nv-space-2);
.origin .nv-steps__body {
max-inline-size: var(--nv-measure);
position: relative;
padding-block-end: var(--nv-space-4);
display: flex;
flex-direction: column;
gap: var(--nv-space-1);
}
.timeline__step::before {
content: "";
position: absolute;
inline-size: var(--nv-space-2);
block-size: var(--nv-space-2);
border-radius: var(--nv-radius-full);
background: var(--nv-color-accent);
inset-inline-start: calc(var(--nv-space-6) * -1 - var(--nv-space-1));
inset-block-start: var(--nv-space-1);
.origin .nv-steps__title {
font-size: var(--nv-font-size-lg);
}
.timeline__when {
color: var(--nv-color-text-tertiary);
.origin .nv-steps__text {
font-size: var(--nv-font-size-md);
color: var(--nv-color-text-secondary);
}
/* --- The stack -------------------------------------------------------------- */
@ -226,29 +208,6 @@
.needs { grid-template-columns: repeat(2, 1fr); }
}
/* --- Numbers ---------------------------------------------------------------- */
.figures {
display: grid;
gap: var(--nv-space-4);
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
/* A card carries no padding of its own -- its parts do -- and a stat tile has
no parts. */
.figure {
display: flex;
flex-direction: column;
gap: var(--nv-space-1);
align-items: flex-start;
padding: var(--nv-space-5);
}
.figure__value {
font-variant-numeric: tabular-nums;
letter-spacing: var(--nv-letter-spacing-tight);
}
/* --- PSOGM ------------------------------------------------------------------ */
.crash {
@ -309,18 +268,15 @@
/* --- Cards ------------------------------------------------------------------- */
/* Niveus's reset makes images block-level, which is right nearly everywhere
and wrong for a mark that belongs beside a title. A flex row rather than
/* A feature's tile belongs beside its title, not above it. A flex row rather than
`display: inline`, so the two stay aligned whatever the title does. */
.nv-card__title:has(.cardmark) {
.nv-card__title:has(.nv-tile) {
display: flex;
align-items: center;
gap: var(--nv-space-2);
gap: var(--nv-space-3);
}
.cardmark {
inline-size: 1.2em;
block-size: 1.2em;
.nv-card__title .nv-tile {
flex: none;
}

View file

@ -199,45 +199,57 @@
<!-- Numbered because this is a sequence: each step only makes sense after
the one above it has happened. -->
<ol class="timeline">
<li class="timeline__step">
<span class="nv-overline timeline__when">Step one</span>
<h3 class="nv-title">The loader</h3>
<p class="nv-body nv-text-secondary">
<ol class="nv-steps nv-steps--vertical origin">
<li class="nv-steps__item">
<span class="nv-steps__marker">1</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Step one</span>
<h3 class="nv-steps__title">The loader</h3>
<p class="nv-steps__text">
A splash, and <b>F8</b> for boot options — including the resolution the
whole machine will come up in. It is a PE/COFF loader built with clang
and lld-link; there is no BIOS path, so the firmware has to be in UEFI
mode.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Step two</span>
<h3 class="nv-title">The kernel log</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item">
<span class="nv-steps__marker">2</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Step two</span>
<h3 class="nv-steps__title">The kernel log</h3>
<p class="nv-steps__text">
On screen, from the first line that can draw. Cores, the PCI bus, the
network card, the filesystem. If it stops, it stops somewhere you can
read.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Step three</span>
<h3 class="nv-title">A shell</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item">
<span class="nv-steps__marker">3</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Step three</span>
<h3 class="nv-steps__title">A shell</h3>
<p class="nv-steps__text">
<code class="nv-code">schinit</code> starts one on the console and a
second on <code class="nv-code">tty2</code>.
<code class="nv-code">mksh</code> is <code class="nv-code">/bin/sh</code>,
with <code class="nv-code">zsh</code> beside it and the real toybox
userland behind both.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Step four</span>
<h3 class="nv-title">Six terminals</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item">
<span class="nv-steps__marker">4</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Step four</span>
<h3 class="nv-steps__title">Six terminals</h3>
<p class="nv-steps__text">
<code class="nv-code">AltGr+F1</code>…<code class="nv-code">F6</code>
switches between them — the one chord a Linux host does not take for
itself — or <code class="nv-code">chvt N</code> from a shell.
</p>
</div>
</li>
</ol>

View file

@ -95,12 +95,19 @@
<p class="nv-caption">GPL-2.0-or-later · runs from RAM · writes nothing to your disks</p>
</div>
<div class="nv-card nv-card--flush console" aria-label="Boot log">
<div class="console__bar">
<span class="nv-badge nv-badge--success"><span class="nv-badge__dot"></span>ttyS0</span>
<span class="nv-caption nv-text-tertiary">SchIFT</span>
<div class="nv-window console" aria-label="Boot log">
<div class="nv-window__titlebar">
<span class="nv-window__controls" aria-hidden="true">
<span class="nv-window__control nv-window__control--close"></span>
<span class="nv-window__control nv-window__control--minimize"></span>
<span class="nv-window__control nv-window__control--zoom"></span>
</span>
<span class="nv-window__title">SchIFT — ttyS0</span>
<span class="nv-window__actions">
<span class="nv-badge nv-badge--success"><span class="nv-badge__dot"></span>live</span>
</span>
</div>
<pre class="nv-code console__log" id="bootlog" aria-live="polite"></pre>
<pre class="nv-window__body nv-code console__log" id="bootlog" aria-live="polite"></pre>
</div>
</header>
@ -118,53 +125,68 @@
<!-- A timeline, not a grid: these happened in this order, and the order is
the point. The rail is what carries that; the labels are its steps. -->
<ol class="timeline">
<li class="timeline__step">
<span class="nv-overline timeline__when">First</span>
<h3 class="nv-title">64-bit, and more than one core</h3>
<p class="nv-body nv-text-secondary">
<ol class="nv-steps nv-steps--vertical origin">
<li class="nv-steps__item" data-state="done">
<span class="nv-steps__marker">1</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">First</span>
<h3 class="nv-steps__title">64-bit, and more than one core</h3>
<p class="nv-steps__text">
Four-level paging, a real SMP bring-up, per-CPU state and a trap path
that survives both. This is the part that invalidates most of what a
32-bit uniprocessor kernel assumes.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Then</span>
<h3 class="nv-title">Its own filesystem</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item" data-state="done">
<span class="nv-steps__marker">2</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Then</span>
<h3 class="nv-steps__title">Its own filesystem</h3>
<p class="nv-steps__text">
xv6's log-structured filesystem was replaced by <b>SchFS</b>: a
copy-on-write B-tree with an uberblock ring, extents and checksummed
metadata. A crash leaves either the old tree or the new one.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Then</span>
<h3 class="nv-title">A Linux-shaped ABI</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item" data-state="done">
<span class="nv-steps__marker">3</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Then</span>
<h3 class="nv-steps__title">A Linux-shaped ABI</h3>
<p class="nv-steps__text">
The syscall table adopted Linux numbering, which is what makes an
unmodified musl and an unmodified toybox run. The table is one
<code class="nv-code">.inc</code> file, and it is the seam the whole
system is built around.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Then</span>
<h3 class="nv-title">Hardware, not emulation</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item" data-state="done">
<span class="nv-steps__marker">4</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Then</span>
<h3 class="nv-steps__title">Hardware, not emulation</h3>
<p class="nv-steps__text">
A UEFI loader, xHCI and USB storage, an e1000 with a real TCP/IP stack,
virtio-gpu and VBE framebuffers, and a device model where a driver never
names its consumer.
</p>
</div>
</li>
<li class="timeline__step">
<span class="nv-overline timeline__when">Now</span>
<h3 class="nv-title">Drivers that are not in the kernel</h3>
<p class="nv-body nv-text-secondary">
<li class="nv-steps__item" aria-current="step">
<span class="nv-steps__marker">5</span>
<div class="nv-steps__body">
<span class="nv-overline nv-text-tertiary">Now</span>
<h3 class="nv-steps__title">Drivers that are not in the kernel</h3>
<p class="nv-steps__text">
A process can be handed a PCI device — its registers, its memory, its
interrupts — and drive it. The GPU driver already runs that way. Nobody
writes a driver for every device that exists; the answer is to stop
requiring that they live inside.
</p>
</div>
</li>
</ol>
</section>
@ -255,7 +277,7 @@
<div class="nv-scroller features">
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title"><img class="cardmark" src="Assets/uberblock.svg" alt="">SchFS</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><img src="Assets/uberblock.svg" alt=""></span>SchFS</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -268,7 +290,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">SMP x86-64 kernel</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="6" width="12" height="12" rx="2"/><path d="M9 2v4M15 2v4M9 18v4M15 18v4M2 9h4M2 15h4M18 9h4M18 15h4"/></svg></span>SMP x86-64 kernel</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -280,7 +302,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">Networking</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3c3 3.5 3 14.5 0 18M12 3c-3 3.5-3 14.5 0 18"/></svg></span>Networking</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -292,7 +314,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">UEFI boot</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3v8"/><path d="M6.3 6.3a8 8 0 1 0 11.4 0"/></svg></span>UEFI boot</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -303,7 +325,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">USB</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 21V4M12 4l-2.5 3M12 4l2.5 3M12 16l-5-3V10M12 14l5-3V9"/><circle cx="7" cy="9" r="1.5"/><rect x="15.5" y="7" width="3" height="3"/></svg></span>USB</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -314,7 +336,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">Virtual terminals</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 9l3 3-3 3M12 15h5"/></svg></span>Virtual terminals</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -327,7 +349,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">schinit</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="5" r="2"/><circle cx="6" cy="19" r="2"/><circle cx="18" cy="19" r="2"/><path d="M12 7v5M12 12l-6 5M12 12l6 5"/></svg></span>schinit</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -340,7 +362,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">A real userland</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3l8 4.5v9L12 21l-8-4.5v-9z"/><path d="M4 7.5l8 4.5 8-4.5M12 12v9"/></svg></span>A real userland</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -353,7 +375,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">Drivers outside the kernel</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="7" width="10" height="10" rx="1.5"/><path d="M6 4v3M10 4v3M6 17v3M10 17v3M16 12h5M18.5 9.5L21 12l-2.5 2.5"/></svg></span>Drivers outside the kernel</h3>
<span class="nv-badge nv-badge--success">runs</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -370,7 +392,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">Schcom</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm" style="--nv-tile-tint: var(--nv-color-warning)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="13" height="10" rx="1.5"/><rect x="8" y="10" width="13" height="10" rx="1.5"/></svg></span>Schcom</h3>
<span class="nv-badge nv-badge--warning">in progress</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -382,7 +404,7 @@
<article class="nv-card">
<div class="nv-card__header">
<h3 class="nv-card__title">SchAPI</h3>
<h3 class="nv-card__title"><span class="nv-tile nv-tile--sm" style="--nv-tile-tint: var(--nv-color-text-tertiary)"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 4c-2 0-3 1-3 3v2c0 1.5-1 3-2 3 1 0 2 1.5 2 3v2c0 2 1 3 3 3M16 4c2 0 3 1 3 3v2c0 1.5 1 3 2 3-1 0-2 1.5-2 3v2c0 2-1 3-3 3"/></svg></span>SchAPI</h3>
<span class="nv-badge">designed</span>
</div>
<div class="nv-card__body nv-text-secondary">
@ -482,12 +504,16 @@
</article>
</div>
<div class="nv-card nv-card--flush console" aria-label="Evicting the GPU driver to userspace">
<div class="console__bar">
<span class="nv-badge nv-badge--success"><span class="nv-badge__dot"></span>tty1</span>
<span class="nv-caption nv-text-tertiary">vgpud</span>
<div class="nv-window console" aria-label="Evicting the GPU driver to userspace">
<div class="nv-window__titlebar">
<span class="nv-window__controls" aria-hidden="true">
<span class="nv-window__control nv-window__control--close"></span>
<span class="nv-window__control nv-window__control--minimize"></span>
<span class="nv-window__control nv-window__control--zoom"></span>
</span>
<span class="nv-window__title">vgpud — tty1</span>
</div>
<pre class="nv-code console__log"><span class="nv-text-tertiary">$ </span>vgpud
<pre class="nv-window__body nv-code console__log"><span class="nv-text-tertiary">$ </span>vgpud
<span class="nv-text-accent">vgpud</span>: virtio-gpu at 00:03.0, currently held by virtio-gpu
<span class="nv-text-accent">virtio-gpu</span>: released to userspace; screen is the VBE framebuffer
<span class="nv-text-accent">vgpud</span>: claimed
@ -513,20 +539,20 @@
<h2 class="nv-heading">The size of it</h2>
</div>
<div class="figures">
<div class="nv-card figure">
<b class="nv-display figure__value">46,961</b>
<span class="nv-label nv-text-secondary">lines in <code class="nv-code">kernel/</code> and <code class="nv-code">include/</code></span>
<dl class="nv-stat-group">
<div class="nv-stat">
<dt class="nv-stat__label">lines in <code class="nv-code">kernel/</code> and <code class="nv-code">include/</code></dt>
<dd class="nv-stat__value">46,961</dd>
</div>
<div class="nv-card figure">
<b class="nv-display figure__value">207</b>
<span class="nv-label nv-text-secondary">syscalls, Linux numbering</span>
</div>
<div class="nv-card figure">
<b class="nv-display figure__value">0</b>
<span class="nv-label nv-text-secondary">patches carried against fastfetch</span>
<div class="nv-stat">
<dt class="nv-stat__label">syscalls, Linux numbering</dt>
<dd class="nv-stat__value">207</dd>
</div>
<div class="nv-stat">
<dt class="nv-stat__label">patches carried against fastfetch</dt>
<dd class="nv-stat__value">0</dd>
</div>
</dl>
</section>
<!-- ======================================================================

View file

@ -57,6 +57,12 @@ the kernel's name (**SchIFT**) as a shape.
- **With or without a wordmark.** Set "SchOS" beside it in **Roboto Bold**,
which is already in the tree (`ports/Roboto`), Apache-2.0, and already
in `NOTICE`.
- **Rendered as an object, drawn as a shape.** The colour `shift.svg` is lit
the way Niveus lights a key -- one light from the upper left, a gloss across
each top face, a specular line on the edges that face it, and a soft shadow
from each slab onto the next. None of that is in the silhouette:
`shift-mask.svg` is the same geometry with no shading, and it is still what
`include/gfx/logo.h` is built from, so the kernel's mark is unchanged.
- Non-human and non-animal, permanently. If a character is ever drawn it gets
its own mark; a logo that starts growing a face has taken that job.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Before After
Before After

View file

@ -8,20 +8,101 @@
without it the slab has no thickness where it is widest, and the corner reads
as a hole rather than an edge.
Drawn the way Niveus draws a key: light falls from the upper left, so every
top face is brightest at its far-left corner and every edge that faces the
light carries a thin specular line. The front faces are lit from above and
darken towards the ground; the end walls face away and are darkest. Each slab
casts a soft shadow on the one below it, which is what makes the stack read
as three objects rather than three stripes.
Geometry is shared with "shift-mask.svg"; see that file.</desc>
<defs>
<!-- top faces: lit corner to far corner -->
<linearGradient id="t1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#A48CFF"/>
<stop offset="0.55" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#6A48F0"/>
</linearGradient>
<linearGradient id="t2" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#8064E6"/>
<stop offset="0.55" stop-color="#5B44C4"/>
<stop offset="1" stop-color="#4E39AE"/>
</linearGradient>
<linearGradient id="t3" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#5A48A8"/>
<stop offset="0.55" stop-color="#3C2E85"/>
<stop offset="1" stop-color="#332772"/>
</linearGradient>
<!-- front faces: lit at the top edge, falling into shade -->
<linearGradient id="f1" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#6E50E8"/>
<stop offset="1" stop-color="#4E35BC"/>
</linearGradient>
<linearGradient id="f2" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#4E3AAE"/>
<stop offset="1" stop-color="#372887"/>
</linearGradient>
<linearGradient id="f3" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#342874"/>
<stop offset="1" stop-color="#231A52"/>
</linearGradient>
<!-- end walls: facing away from the light -->
<linearGradient id="w1" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#4F36B4"/>
<stop offset="1" stop-color="#3A2690"/>
</linearGradient>
<linearGradient id="w2" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#3A2A86"/>
<stop offset="1" stop-color="#2B1F68"/>
</linearGradient>
<linearGradient id="w3" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#261C56"/>
<stop offset="1" stop-color="#1A133E"/>
</linearGradient>
<!-- the gloss across each top face, strongest at its back edge -->
<linearGradient id="gloss" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#FFFFFF" stop-opacity="0.38"/>
<stop offset="0.45" stop-color="#FFFFFF" stop-opacity="0.08"/>
<stop offset="1" stop-color="#FFFFFF" stop-opacity="0"/>
</linearGradient>
<filter id="soft" x="-20%" y="-40%" width="140%" height="180%">
<feGaussianBlur stdDeviation="4"/>
</filter>
</defs>
<!-- contact shadows, each cast down and to the right of its slab -->
<path fill="#000" opacity="0.35" filter="url(#soft)" d="M58 138 L160 138 L132 170 L28 170 Z"/>
<path fill="#000" opacity="0.30" filter="url(#soft)" d="M76 96 L178 96 L150 128 L46 128 Z"/>
<path fill="#000" opacity="0.26" filter="url(#soft)" d="M94 54 L196 54 L168 86 L64 86 Z"/>
<!-- bottom slab -->
<path fill="#3C2E85" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="#31256E" d="M24 156 L128 156 L128 167 L24 167 Z"/>
<path fill="#291F5C" d="M158 126 L158 137 L128 167 L128 156 Z"/>
<path fill="url(#t3)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="url(#gloss)" d="M54 126 L158 126 L128 156 L24 156 Z"/>
<path fill="url(#f3)" d="M24 156 L128 156 L128 167 L24 167 Z"/>
<path fill="url(#w3)" d="M158 126 L158 137 L128 167 L128 156 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.35" stroke-width="1.2"
stroke-linecap="round" d="M24.6 155.4 L54.4 126.6 L157 126.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.16" stroke-width="1"
d="M24 156.5 L128 156.5"/>
<!-- middle slab -->
<path fill="#5B44C4" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="#4B37A6" d="M42 114 L146 114 L146 125 L42 125 Z"/>
<path fill="#3F2D8C" d="M176 84 L176 95 L146 125 L146 114 Z"/>
<path fill="url(#t2)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="url(#gloss)" d="M72 84 L176 84 L146 114 L42 114 Z"/>
<path fill="url(#f2)" d="M42 114 L146 114 L146 125 L42 125 Z"/>
<path fill="url(#w2)" d="M176 84 L176 95 L146 125 L146 114 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.42" stroke-width="1.2"
stroke-linecap="round" d="M42.6 113.4 L72.4 84.6 L175 84.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.18" stroke-width="1"
d="M42 114.5 L146 114.5"/>
<!-- top slab -->
<path fill="#7C5CFF" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="#6949E0" d="M60 72 L164 72 L164 83 L60 83 Z"/>
<path fill="#5B3FC9" d="M194 42 L194 53 L164 83 L164 72 Z"/>
<path fill="url(#t1)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="url(#gloss)" d="M90 42 L194 42 L164 72 L60 72 Z"/>
<path fill="url(#f1)" d="M60 72 L164 72 L164 83 L60 83 Z"/>
<path fill="url(#w1)" d="M194 42 L194 53 L164 83 L164 72 Z"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.55" stroke-width="1.2"
stroke-linecap="round" d="M60.6 71.4 L90.4 42.6 L193 42.6"/>
<path fill="none" stroke="#FFFFFF" stroke-opacity="0.22" stroke-width="1"
d="M60 72.5 L164 72.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Before After
Before After

View file

@ -20,10 +20,66 @@
survives include/gfx/logo.h, which is a single coverage channel and keeps no
colour at all.
Drawn as Niveus draws a dial: the slots are raised keys set into a groove
cut into the surface, bevelled by one light from the upper left, and the
newest slot and the root are lit from inside. The geometry is unchanged.
Stands alone, with no reference to SchOS, as projects/schfs-linux/README.md
requires.</desc>
<g fill="#3C2E85">
<defs>
<!-- one light for the whole dial, so every slot is lit from the same side -->
<linearGradient id="slot" gradientUnits="userSpaceOnUse" x1="20" y1="20" x2="180" y2="180">
<stop offset="0" stop-color="#5A47B0"/>
<stop offset="0.5" stop-color="#3C2E85"/>
<stop offset="1" stop-color="#2A2066"/>
</linearGradient>
<linearGradient id="lit" gradientUnits="userSpaceOnUse" x1="120" y1="10" x2="160" y2="56">
<stop offset="0" stop-color="#B09CFF"/>
<stop offset="0.5" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#5A3BE0"/>
</linearGradient>
<radialGradient id="root" cx="0.38" cy="0.34" r="0.7">
<stop offset="0" stop-color="#E4DCFF"/>
<stop offset="0.3" stop-color="#9F86FF"/>
<stop offset="0.75" stop-color="#7C5CFF"/>
<stop offset="1" stop-color="#4E32C8"/>
</radialGradient>
<radialGradient id="groove" cx="0.5" cy="0.5" r="0.5">
<stop offset="0.5" stop-color="#0E0B1E" stop-opacity="0"/>
<stop offset="0.62" stop-color="#0E0B1E" stop-opacity="0.55"/>
<stop offset="0.92" stop-color="#0E0B1E" stop-opacity="0.55"/>
<stop offset="1" stop-color="#0E0B1E" stop-opacity="0"/>
</radialGradient>
<radialGradient id="halo" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" stop-color="#9F86FF" stop-opacity="0.55"/>
<stop offset="1" stop-color="#7C5CFF" stop-opacity="0"/>
</radialGradient>
<!-- The bevel: the shape's own alpha, blurred into a height map and lit
from the upper left, added back over the fill. -->
<filter id="bevel" x="-10%" y="-10%" width="120%" height="120%">
<feGaussianBlur in="SourceAlpha" stdDeviation="1.6" result="h"/>
<feSpecularLighting in="h" surfaceScale="3" specularConstant="0.85"
specularExponent="16" lighting-color="#FFFFFF" result="s">
<feDistantLight azimuth="225" elevation="40"/>
</feSpecularLighting>
<feComposite in="s" in2="SourceAlpha" operator="in" result="sa"/>
<feComposite in="SourceGraphic" in2="sa" operator="arithmetic" k2="1" k3="0.55"/>
</filter>
<filter id="drop" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceAlpha" stdDeviation="2.5"/>
<feOffset dx="1.5" dy="2.5" result="o"/>
<feComponentTransfer><feFuncA type="linear" slope="0.5"/></feComponentTransfer>
<feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<!-- the groove the slots sit in -->
<circle cx="100" cy="100" r="86" fill="url(#groove)"/>
<g filter="url(#drop)">
<g fill="url(#slot)" filter="url(#bevel)">
<path d="M85.93 20.23 A81.00 81.00 0 0 1 114.07 20.23 L110.25 41.90 A59.00 59.00 0 0 0 89.75 41.90 Z"/>
<path d="M162.05 47.93 A81.00 81.00 0 0 1 176.12 72.30 L155.44 79.82 A59.00 59.00 0 0 0 145.20 62.08 Z"/>
<path d="M179.77 85.93 A81.00 81.00 0 0 1 179.77 114.07 L158.10 110.25 A59.00 59.00 0 0 0 158.10 89.75 Z"/>
@ -36,9 +92,16 @@
<path d="M23.88 72.30 A81.00 81.00 0 0 1 37.95 47.93 L54.80 62.08 A59.00 59.00 0 0 0 44.56 79.82 Z"/>
<path d="M47.93 37.95 A81.00 81.00 0 0 1 72.30 23.88 L79.82 44.56 A59.00 59.00 0 0 0 62.08 54.80 Z"/>
</g>
<g fill="#7C5CFF">
<path d="M132.15 11.67 A94.00 94.00 0 0 1 160.42 27.99 L137.92 54.80 A59.00 59.00 0 0 0 120.18 44.56 Z"/>
<circle cx="100" cy="100" r="20"/>
</g>
<!-- the newest slot and the root it names, lit from inside -->
<circle cx="141" cy="36" r="32" fill="url(#halo)"/>
<circle cx="100" cy="100" r="34" fill="url(#halo)"/>
<g filter="url(#drop)">
<g filter="url(#bevel)">
<path fill="url(#lit)" d="M132.15 11.67 A94.00 94.00 0 0 1 160.42 27.99 L137.92 54.80 A59.00 59.00 0 0 0 120.18 44.56 Z"/>
<circle cx="100" cy="100" r="20" fill="url(#root)"/>
</g>
</g>
<ellipse cx="93" cy="92" rx="6.5" ry="4" fill="#FFFFFF" opacity="0.55"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Before After
Before After