ZhuoQi Devzhuoqidev.comRSSllms.txt

← All entries~/design/handmade-paper

Visual stylesOriginal

Handmade Paper Feel

Cream paper with a dot grid; stamp red, pen blue, highlighter yellow; serif headings, notes, sticky notes, stamps, full dark mode.

html · cssMITAdded #handmade#paper feel#color palette#dark mode#design guidelines

Live demoOpen in a new tab ↗

What makes it work

  • A sheet of paper as the base: cream --paper plus a dot grid at 22px spacing (one radial-gradient is enough); cards are a bit whiter than the paper, as if a card were stuck onto it.
  • Three pens: pen blue (links, primary buttons, dashed borders), stamp red (numbering, annotations, stamps), and highlighter yellow (emphasis, heading underlines, sticky notes). Each color has one job, so the page doesn’t get messy.
  • Four voices: headings in a bold serif (Songti), body in the system sans-serif (line height 1.9), labels / dates in monospace, and the handwriting font only on large headings and annotations, so body text always stays readable.
  • The highlighter is a real highlighter: short phrases use .mark with a gradient on the lower half; long headings use text-decoration with a thick underline pulled upward (text-underline-offset: -.2em), which also follows line wraps.
  • Small objects on the paper: a sticky note tilted 3 degrees, translucent striped tape, a square seal with vertical text, a round stamp with an inner margin, and a tilted round stamp used as a callout icon.
  • Dark is a desk at night: the background, ink and the three pens each have a night value (the demo shows both palettes side by side); “physical objects” such as sticky notes and the terminal mostly keep their original colors. The button in the top bar switches manually, and the choice is stored in localStorage.

How to use it

  1. Copy the :root variables and the two night-value blocks: :root[data-theme="dark"] and @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) … }.
  2. Copy the dot-grid line for the body background as it is; copy the components you need by class name: .card / .tape / .sticky / .seal / .stamp-round / .chip-btn / .tag / .mark / .callout.
  3. For manual switching: put the inline script at the start of the demo in <head> (it restores the theme before the first frame, with no flash), and copy the button script at the bottom.
  4. Swap fonts to suit your site: the demo uses only system fonts, with the handwriting face falling back to a Kai typeface. For a more handwritten feel, pick an open-source handwriting font yourself.

Pitfalls

  • The night values have to be written twice (one for the manual choice, one for following the system); miss one and you get “the system is dark, but manually switching to light still shows dark”.
  • A block-level pseudo-element like .t-h2::before inherits the heading’s text-decoration, so the numbering also gets highlighted; changing it to inline-block; width: 100% avoids this.
  • Highlighter yellow is glaring on a dark background; at night switch to dark gold (#7d6416), and also lower the semi-transparent yellow used for emphasis.
  • Chinese handwriting fonts are huge (several MB); always subset to the characters the page actually uses. Without subsetting, the performance score on phones drops a lot.
  • Sticky notes and the terminal keep the same colors in both modes, so the text color inside them must be hard-coded rather than using --ink, which changes with the theme.
$For agents: index.md

Source MIT licensed. Take it.

<!doctype html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>手作纸感</title>
    <script>
      // Restore a theme picked with the button before first paint; otherwise follow the system.
      try {
        const saved = localStorage.getItem("paper-theme");
        if (saved) document.documentElement.dataset.theme = saved;
      } catch {}
    </script>
    <style>
      :root {
        --paper: #fbf8f1;
        --paper-2: #f3eee2;
        --card: #fffdf8;
        --ink: #1c2230;
        --ink-2: #4a5163;
        --ink-3: #636877;
        --line: #e6dfd0;
        --dot: #d8d0bf;
        --blue: #2f5bd3;
        --blue-soft: #e8eefc;
        --blue-line: rgba(47, 91, 211, 0.35);
        --seal: #c0391f;
        --seal-soft: #fbe7e2;
        --stamp: #c0391f; /* seal background behind cream text, the same in both themes */
        --hi: #ffe066;
        --hi-strong: rgba(255, 224, 102, 0.55);
        --note: #ffe88a;
        --term: #161a22;
        --term-green: #5fd38a;
        --yellow: #ffe066;
        --green: #277a4b;
        --callout: #fff6f3;
        --code-ink: #9b2f1c;
        --on-blue: #fff;
        --topbar: rgba(251, 248, 241, 0.86);
        --shadow: 0 1px 0 rgba(28, 34, 48, 0.04), 0 10px 28px -14px rgba(28, 34, 48, 0.28);
        --ease: cubic-bezier(0.16, 1, 0.3, 1);
        --spring: linear(
          0,
          0.062,
          0.215,
          0.411,
          0.615,
          0.799,
          0.95,
          1.059,
          1.126,
          1.158,
          1.161,
          1.145,
          1.116,
          1.083,
          1.051,
          1.023,
          1.001,
          0.986,
          0.977,
          0.974,
          0.974,
          0.978,
          0.983,
          0.988,
          0.994,
          0.998,
          1.001,
          1.003,
          1.004,
          1.004,
          1
        );
        /* System fonts only. Four voices: serif headings, sans body, mono labels, hand-written accents. */
        --f-serif:
          "Songti SC", STSong, "Noto Serif CJK SC", "Source Han Serif SC", SimSun, "AR PL UMing CN", Georgia, serif;
        --f-sans: system-ui, -apple-system, "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
        --f-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
        --f-hand: "Kaiti SC", STKaiti, KaiTi, "AR PL UKai CN", "Segoe Print", "Bradley Hand", cursive;
        color-scheme: light;
      }
      /* Night desk: an explicit choice (data-theme) wins; otherwise the system setting decides. */
      :root[data-theme="dark"] {
        --paper: #14161b;
        --paper-2: #1c1f26;
        --card: #1e2129;
        --ink: #ece7dc;
        --ink-2: #bab6ac;
        --ink-3: #959aa8;
        --line: #31353f;
        --dot: #2c3039;
        --blue: #8eaaff;
        --blue-soft: #1f2a47;
        --blue-line: rgba(142, 170, 255, 0.45);
        --seal: #f0694e;
        --seal-soft: #3b211b;
        --hi: #7d6416;
        --hi-strong: rgba(255, 214, 90, 0.26);
        --note: #ecd77e;
        --term: #0d0f13;
        --green: #5cc189;
        --callout: #2a1915;
        --code-ink: #f4957f;
        --on-blue: #14161b;
        --topbar: rgba(20, 22, 27, 0.86);
        --shadow: 0 1px 0 rgba(0, 0, 0, 0.25), 0 10px 28px -14px rgba(0, 0, 0, 0.8);
        color-scheme: dark;
      }
      @media (prefers-color-scheme: dark) {
        :root:not([data-theme="light"]) {
          --paper: #14161b;
          --paper-2: #1c1f26;
          --card: #1e2129;
          --ink: #ece7dc;
          --ink-2: #bab6ac;
          --ink-3: #959aa8;
          --line: #31353f;
          --dot: #2c3039;
          --blue: #8eaaff;
          --blue-soft: #1f2a47;
          --blue-line: rgba(142, 170, 255, 0.45);
          --seal: #f0694e;
          --seal-soft: #3b211b;
          --hi: #7d6416;
          --hi-strong: rgba(255, 214, 90, 0.26);
          --note: #ecd77e;
          --term: #0d0f13;
          --green: #5cc189;
          --callout: #2a1915;
          --code-ink: #f4957f;
          --on-blue: #14161b;
          --topbar: rgba(20, 22, 27, 0.86);
          --shadow: 0 1px 0 rgba(0, 0, 0, 0.25), 0 10px 28px -14px rgba(0, 0, 0, 0.8);
          color-scheme: dark;
        }
      }

      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
        /* Dotted paper: one radial-gradient dot per 22px cell. */
        background: var(--paper) radial-gradient(var(--dot) 1px, transparent 1.2px) 0 0 / 22px 22px;
        color: var(--ink);
        font: 400 16px/1.75 var(--f-sans);
        -webkit-font-smoothing: antialiased;
      }
      a {
        color: inherit;
      }
      :focus-visible {
        outline: 2px solid var(--blue);
        outline-offset: 2px;
      }

      /* ---------- top bar ---------- */
      .topbar {
        position: sticky;
        top: 0;
        z-index: 10;
        display: flex;
        align-items: center;
        gap: 12px;
        height: 60px;
        padding: 0 16px;
        background: var(--topbar);
        -webkit-backdrop-filter: blur(8px);
        backdrop-filter: blur(8px);
        border-bottom: 2px dashed var(--blue-line);
      }
      .brand {
        display: flex;
        align-items: center;
        gap: 12px;
        text-decoration: none;
      }
      .brand b {
        display: block;
        font: 700 17px/1.1 var(--f-serif);
      }
      .brand small {
        font: 400 11px/1.2 var(--f-mono);
        color: var(--ink-3);
        letter-spacing: 0.04em;
      }
      .spacer {
        flex: 1;
      }

      /* ---------- seals and stamps ---------- */
      .seal {
        display: grid;
        place-items: center;
        flex: none;
        width: 36px;
        height: 36px;
        background: var(--stamp);
        color: #fff8ef;
        border-radius: 6px;
        transform: rotate(-4deg);
        font: 900 13px/1.05 var(--f-serif);
        letter-spacing: 1px;
        writing-mode: vertical-rl;
        box-shadow: inset 0 0 0 2px rgba(255, 248, 239, 0.55);
      }
      .seal.big {
        width: 64px;
        height: 64px;
        font-size: 22px;
        border-radius: 8px;
        box-shadow: inset 0 0 0 3px rgba(255, 248, 239, 0.55);
      }
      .stamp-round {
        display: grid;
        place-items: center;
        flex: none;
        width: 64px;
        height: 64px;
        border-radius: 50%;
        border: 2.5px solid var(--seal);
        color: var(--seal);
        font: 800 14px/1 var(--f-mono);
        letter-spacing: 0.04em;
        transform: rotate(-8deg);
        /* the inner ring: a card-coloured gap, then a thin seal-coloured line */
        box-shadow:
          inset 0 0 0 4px var(--card),
          inset 0 0 0 5.5px var(--seal);
      }
      .stamp-round:nth-child(3) {
        transform: rotate(6deg);
      }
      .stamp-round:nth-child(4) {
        transform: rotate(-3deg);
      }

      /* ---------- buttons, tags, marks ---------- */
      .chip-btn {
        font: 500 13px/1 var(--f-sans);
        color: var(--ink-2);
        padding: 8px 12px;
        border-radius: 10px;
        border: 1px dashed var(--ink-3);
        background: transparent;
        cursor: pointer;
        text-decoration: none;
        white-space: nowrap;
        transition:
          scale 0.45s var(--spring),
          color 0.15s,
          background-color 0.15s;
      }
      .chip-btn:hover {
        border-style: solid;
        color: var(--ink);
        background: var(--card);
      }
      .chip-btn:active {
        scale: 0.93;
      }
      .chip-btn.solid {
        border: 1px solid var(--blue);
        background: var(--blue);
        color: var(--on-blue);
      }
      .chip-btn.ink {
        border: 1px solid var(--ink);
        background: var(--ink);
        color: var(--paper);
      }
      .tag {
        display: inline-block;
        padding: 3px 8px;
        border-radius: 6px;
        font: 500 11px/1.4 var(--f-mono);
        color: var(--blue);
        background: var(--blue-soft);
      }
      .tag.red {
        color: var(--seal);
        background: var(--seal-soft);
      }
      /* Highlighter: a band across the lower part of the text, not the whole line box. */
      .mark {
        padding: 0 4px;
        background: linear-gradient(transparent 58%, var(--hi) 58%, var(--hi) 92%, transparent 92%);
      }
      .kicker {
        font: 500 11px/1 var(--f-mono);
        letter-spacing: 0.12em;
        text-transform: uppercase;
        color: var(--ink-3);
      }

      /* ---------- layout ---------- */
      main {
        max-width: 1140px;
        margin: 0 auto;
        padding: 26px 16px 60px;
      }
      .hero-row {
        display: grid;
        grid-template-columns: minmax(0, 1fr) 260px;
        gap: 32px;
        align-items: center;
        margin-bottom: 26px;
      }
      .hero h1 {
        margin: 0;
        font: 400 52px/1.15 var(--f-hand);
      }
      .hero p {
        margin: 6px 0 0;
        font: 400 22px/1.3 var(--f-hand);
        color: var(--blue);
      }
      .hero .sub {
        margin-top: 12px;
        font: 400 12px/1.6 var(--f-mono);
        color: var(--ink-3);
        letter-spacing: 0.06em;
      }
      .grid {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 22px;
        align-items: start;
      }
      .span {
        grid-column: 1 / -1;
      }

      /* ---------- cards ---------- */
      .card {
        position: relative;
        padding: 20px 22px;
        background: var(--card);
        border: 2px dashed var(--blue-line);
        border-radius: 14px;
        box-shadow: var(--shadow);
      }
      .card > .kicker {
        display: block;
        margin-bottom: 12px;
      }
      a.card {
        display: block;
        text-decoration: none;
        transition:
          transform 0.6s var(--spring),
          border-color 0.2s;
      }
      a.card:hover {
        border-style: solid;
        border-color: var(--blue);
        transform: translateY(-3px) rotate(-0.4deg);
      }
      .tape {
        --t: 255, 214, 61;
        position: absolute;
        top: -9px;
        left: 50%;
        width: 78px;
        height: 18px;
        transform: translateX(-50%) rotate(-3deg);
        background: repeating-linear-gradient(90deg, rgba(var(--t), 0.9) 0 5px, rgba(var(--t), 0.45) 5px 10px);
        border-radius: 1px;
      }
      .tape.blue {
        --t: 47, 91, 211;
        opacity: 0.55;
      }

      /* ---------- palette ---------- */
      .swatches {
        display: grid;
        grid-template-columns: repeat(10, minmax(0, 1fr));
        gap: 10px;
      }
      .swatches + .kicker {
        display: block;
        margin: 16px 0 12px;
      }
      .sw {
        margin: 0;
        font: 400 11px/1.35 var(--f-mono);
        color: var(--ink-2);
      }
      .sw i {
        display: block;
        height: 44px;
        margin-bottom: 6px;
        border-radius: 8px;
        background: var(--c);
        box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1);
      }
      .sw b {
        display: block;
        font-weight: 600;
        color: var(--ink);
      }

      /* ---------- sticky note ---------- */
      .sticky {
        position: relative;
        margin: 0;
        padding: 24px 22px 18px;
        background: var(--note);
        border-radius: 4px;
        transform: rotate(3deg);
        box-shadow: 0 16px 24px -16px rgba(120, 90, 0, 0.45);
      }
      .sticky blockquote {
        margin: 0;
        font: 400 24px/1.35 var(--f-hand);
        color: #3b2f05; /* paper-coloured note: dark ink in both themes */
      }
      .sticky figcaption {
        margin-top: 12px;
        font: 400 11px/1.5 var(--f-mono);
        color: #7a6510;
      }

      /* ---------- type ---------- */
      .t-display {
        margin: 0 0 6px;
        font: 900 36px/1.25 var(--f-serif);
      }
      .t-h2 {
        margin: 18px 0 8px;
        font: 900 24px/1.4 var(--f-serif);
        /* A highlighter stroke that follows the text across line breaks. */
        text-decoration: underline;
        text-decoration-color: var(--hi);
        text-decoration-thickness: 0.34em;
        text-underline-offset: -0.2em;
        text-decoration-skip-ink: none;
      }
      .t-h2::before {
        content: "§01";
        /* inline-block: a block child would inherit the heading's highlighter underline */
        display: inline-block;
        width: 100%;
        margin-bottom: 8px;
        font: 500 12px/1 var(--f-mono);
        color: var(--seal);
        letter-spacing: 0.12em;
      }
      .t-h3 {
        margin: 14px 0 4px;
        font: 700 18px/1.5 var(--f-serif);
      }
      .t-h3::before {
        content: "▸ ";
        color: var(--blue);
      }
      .prose {
        margin: 0 0 10px;
        font-size: 15.5px;
        line-height: 1.9;
        color: var(--ink-2);
      }
      .prose strong {
        color: var(--ink);
        background: linear-gradient(transparent 70%, var(--hi-strong) 70%);
      }
      .prose a {
        color: var(--blue);
        text-decoration-color: var(--blue-line);
        text-underline-offset: 3px;
      }
      .prose em {
        font-style: normal;
        font-weight: 500;
        color: var(--ink);
        /* Chinese emphasis dots under each character instead of italics. */
        text-emphasis: dot var(--seal);
        text-emphasis-position: under right;
      }
      .prose code {
        font: 400 0.86em/1 var(--f-mono);
        padding: 2px 6px;
        border-radius: 5px;
        background: var(--paper-2);
        border: 1px solid var(--line);
        color: var(--code-ink);
      }
      .type-row {
        display: flex;
        flex-wrap: wrap;
        gap: 8px 18px;
        align-items: baseline;
        padding-top: 12px;
        border-top: 1px dashed var(--line);
      }
      .margin-note {
        display: inline-flex;
        align-items: flex-end;
        gap: 4px;
        font: 400 22px/1.2 var(--f-hand);
        color: var(--seal);
        transform: rotate(-4deg);
      }

      /* ---------- components ---------- */
      .memo h3 {
        margin: 6px 0 6px;
        font: 700 17px/1.45 var(--f-serif);
      }
      .memo p {
        margin: 0 0 12px;
        font-size: 13.5px;
        line-height: 1.7;
        color: var(--ink-2);
      }
      .tags {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
      }
      .row {
        display: flex;
        flex-wrap: wrap;
        gap: 12px;
        align-items: center;
      }
      .row + .row {
        margin-top: 16px;
      }
      .callout {
        display: flex;
        gap: 14px;
        align-items: flex-start;
        margin-top: 18px;
        padding: 14px 16px;
        border: 1.5px solid var(--seal);
        border-radius: 12px;
        background: var(--callout);
        font-size: 14px;
        line-height: 1.75;
        color: var(--ink-2);
      }
      .callout .stamp {
        flex: none;
        display: grid;
        place-items: center;
        width: 42px;
        height: 42px;
        border-radius: 50%;
        border: 2px solid var(--seal);
        color: var(--seal);
        font: 900 13px/1 var(--f-serif);
        transform: rotate(-10deg);
      }
      .term {
        margin-top: 18px;
        padding: 12px 16px;
        border-radius: 12px;
        background: var(--term);
        color: #d7dce6;
        font: 400 12.5px/1.7 var(--f-mono);
      }
      .term .p {
        color: var(--term-green);
      }
      .term .y {
        background: var(--yellow);
        color: #161a22;
        padding: 1px 6px;
        border-radius: 3px;
      }

      @media (max-width: 860px) {
        .swatches {
          grid-template-columns: repeat(5, minmax(0, 1fr));
          gap: 10px 8px;
        }
        .sw {
          font-size: 10px;
        }
        .hero-row,
        .grid {
          grid-template-columns: minmax(0, 1fr);
        }
        .sticky {
          max-width: 300px;
          margin: 8px auto 0;
        }
      }
      @media (max-width: 520px) {
        .brand small {
          display: none;
        }
        .hero h1 {
          font-size: 38px;
        }
        .hero p {
          font-size: 19px;
        }
        .t-display {
          font-size: 28px;
        }
        .card {
          padding: 18px 16px;
        }
      }
      @media (prefers-reduced-motion: reduce) {
        *,
        *::before,
        *::after {
          transition: none !important;
        }
      }
    </style>
  </head>
  <body>
    <header class="topbar">
      <a class="brand" href="#">
        <span class="seal" aria-hidden="true">纸本</span>
        <span><b>小王的纸本</b><small>notes · 手记</small></span>
      </a>
      <span class="spacer"></span>
      <button class="chip-btn" type="button" id="theme" aria-pressed="false">☾ 夜间</button>
    </header>

    <main>
      <div class="hero-row">
        <section class="hero">
          <h1>把笔记写成<span class="mark">一张纸</span></h1>
          <p>cream paper · pen blue · seal red · highlighter</p>
          <div class="sub">奶油纸 + 点阵底 · 印章红 / 钢笔蓝 / 荧光黄 · 深色模式齐全</div>
        </section>
        <figure class="sticky">
          <span class="tape" aria-hidden="true"></span>
          <blockquote>手写体只用在标题和批注上,正文仍然好读。</blockquote>
          <figcaption>— 便利贴 · .sticky</figcaption>
        </figure>
      </div>

      <div class="grid">
        <section class="card span" aria-labelledby="pal-h">
          <span class="kicker" id="pal-h">Palette · 日间</span>
          <div class="swatches">
            <figure class="sw" style="--c: #fbf8f1"><i></i><b>--paper</b>#fbf8f1</figure>
            <figure class="sw" style="--c: #fffdf8"><i></i><b>--card</b>#fffdf8</figure>
            <figure class="sw" style="--c: #e6dfd0"><i></i><b>--line</b>#e6dfd0</figure>
            <figure class="sw" style="--c: #1c2230"><i></i><b>--ink</b>#1c2230</figure>
            <figure class="sw" style="--c: #4a5163"><i></i><b>--ink-2</b>#4a5163</figure>
            <figure class="sw" style="--c: #2f5bd3"><i></i><b>--blue</b>#2f5bd3</figure>
            <figure class="sw" style="--c: #c0391f"><i></i><b>--seal</b>#c0391f</figure>
            <figure class="sw" style="--c: #ffe066"><i></i><b>--hi</b>#ffe066</figure>
            <figure class="sw" style="--c: #ffe88a"><i></i><b>--note</b>#ffe88a</figure>
            <figure class="sw" style="--c: #161a22"><i></i><b>--term</b>#161a22</figure>
          </div>
          <span class="kicker">Palette · 夜间</span>
          <div class="swatches">
            <figure class="sw" style="--c: #14161b"><i></i><b>--paper</b>#14161b</figure>
            <figure class="sw" style="--c: #1e2129"><i></i><b>--card</b>#1e2129</figure>
            <figure class="sw" style="--c: #31353f"><i></i><b>--line</b>#31353f</figure>
            <figure class="sw" style="--c: #ece7dc"><i></i><b>--ink</b>#ece7dc</figure>
            <figure class="sw" style="--c: #bab6ac"><i></i><b>--ink-2</b>#bab6ac</figure>
            <figure class="sw" style="--c: #8eaaff"><i></i><b>--blue</b>#8eaaff</figure>
            <figure class="sw" style="--c: #f0694e"><i></i><b>--seal</b>#f0694e</figure>
            <figure class="sw" style="--c: #7d6416"><i></i><b>--hi</b>#7d6416</figure>
            <figure class="sw" style="--c: #ecd77e"><i></i><b>--note</b>#ecd77e</figure>
            <figure class="sw" style="--c: #0d0f13"><i></i><b>--term</b>#0d0f13</figure>
          </div>
        </section>

        <section class="card" aria-labelledby="type-h">
          <span class="kicker" id="type-h">Type · 四种声音</span>
          <p class="t-display">标题用宋体,粗一点</p>
          <h2 class="t-h2">二级标题带一道荧光笔</h2>
          <h3 class="t-h3">三级标题前面一个蓝色小三角</h3>
          <p class="prose">
            正文用系统无衬线,行高放到 1.9。<strong>重点</strong>用半截荧光黄,<a href="#">链接</a>是钢笔蓝,
            中文强调不用斜体而是<em>着重号</em>,行内代码是 <code>--seal</code> 这样的小纸条。
          </p>
          <div class="type-row">
            <span class="kicker">mono · 标签 / 日期</span>
            <span class="margin-note"
              >手写批注
              <svg width="34" height="22" viewBox="0 0 34 22" aria-hidden="true">
                <path
                  d="M2 4 C 12 16, 22 18, 31 12 M24 8 L31 12 L25 19"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                  stroke-linecap="round"
                  stroke-linejoin="round"
                /></svg
            ></span>
          </div>
        </section>

        <section class="card" aria-labelledby="comp-h">
          <span class="kicker" id="comp-h">Pieces · 小部件</span>
          <a class="card memo" href="#">
            <span class="tape blue" aria-hidden="true"></span>
            <span class="kicker">笔记 · 10-12</span>
            <h3>虚线卡片,悬停变实线</h3>
            <p>边框是半透明的钢笔蓝虚线,鼠标放上来变成实线并轻轻抬起。</p>
            <span class="tags"><span class="tag">css</span><span class="tag red">手作感</span></span>
          </a>
          <div class="row" style="margin-top: 22px">
            <span class="seal big" aria-hidden="true">小王</span>
            <span class="stamp-round">MIT</span>
            <span class="stamp-round">2026</span>
            <span class="stamp-round">OK</span>
          </div>
          <div class="row">
            <button class="chip-btn" type="button">虚线按钮</button>
            <button class="chip-btn solid" type="button">主要按钮</button>
            <button class="chip-btn ink" type="button">墨色按钮</button>
          </div>
          <div class="callout">
            <span class="stamp" aria-hidden="true">注意</span>
            <div>提示框是一枚歪着的圆章加一圈印章红的细框,比图标更有纸上的感觉。</div>
          </div>
          <div class="term"><span class="p">$</span> echo "see you" <span class="y">[done]</span></div>
        </section>
      </div>
    </main>

    <script>
      // Theme button: flips data-theme and remembers it. Without JS the system setting still applies.
      const root = document.documentElement;
      const btn = document.getElementById("theme");
      const systemDark = matchMedia("(prefers-color-scheme: dark)");
      const current = () => root.dataset.theme ?? (systemDark.matches ? "dark" : "light");
      function paint() {
        const dark = current() === "dark";
        btn.setAttribute("aria-pressed", String(dark));
        btn.textContent = dark ? "☀ 日间" : "☾ 夜间";
      }
      btn.addEventListener("click", () => {
        root.dataset.theme = current() === "dark" ? "light" : "dark";
        try {
          localStorage.setItem("paper-theme", root.dataset.theme);
        } catch {}
        paint();
      });
      systemDark.addEventListener("change", paint);
      paint();
    </script>
  </body>
</html>

Say hi on WeChat

Liu ZhuoQi's WeChat QR code

Scan it in WeChat, or long-press it on your phone

Mention why you're reaching out, or I might miss it.