/* The site's shared styles (secretsantanamegenerator.com). Writers don't edit
   this file: page-only styles go in styles/pages/<slug>.css (docs/WRITERS.md).

   Gift tags: every page is a sheet of paper under a band of kraft; the draw
   tool's steps are card tags threaded on baker's twine; a link opens on a
   parcel (/r/), its tag hanging from a ribbon bow, and the tag turns over to
   show the name. No gradients for show, no glow, no motion but the tag's turn.
   Fonts are self-hosted (SIL Open Font License, see assets/fonts/OFL.txt):
   the privacy page promises no third-party fonts. font-display: optional
   means a slow connection keeps the fallback instead of swapping text late. */

@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 600;
  font-display: optional;
  src: url(/assets/fonts/fraunces-600-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fraunces";
  font-style: normal;
  font-weight: 600;
  font-display: optional;
  src: url(/assets/fonts/fraunces-600-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 400;
  font-display: optional;
  src: url(/assets/fonts/fraunces-400i-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Fraunces";
  font-style: italic;
  font-weight: 400;
  font-display: optional;
  src: url(/assets/fonts/fraunces-400i-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 400 700;
  font-display: optional;
  src: url(/assets/fonts/figtree-latin.woff2) format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Figtree";
  font-style: normal;
  font-weight: 400 700;
  font-display: optional;
  src: url(/assets/fonts/figtree-latin-ext.woff2) format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


:root {
  /* paper: kraft for the parcel (the card page, and the band behind the draw
     page's title), a paler kraft sheet under the long draw page */
  --ground: #d5bc94;
  --paper: #ebdfc8;
  --band-bg: #d5bc94;
  --ground-ink: #2a2017;
  --ground-muted: #46372a;
  --tag: #fbf7ee;             /* card stock */
  --tag-2: #f3ebdb;           /* a sheet laid on the card */
  --tag-edge: #d6c4a2;        /* the cut edge of the card */
  --field: #fffdf8;
  --chip: #e8d6b3;            /* small kraft tags for names */
  --ring: #eadcc0;            /* reinforcement ring round a punched hole */
  /* ink */
  --ink: #2a2017;
  --muted: #5d4f40;
  --line: #e3d6bf;
  --rule: #d8c7a8;
  --line-strong: #8a7760;
  /* holiday colours */
  --accent: #1f4d38;          /* pine */
  --accent-hover: #163a2a;
  --accent-ink: #fbf7ee;
  --accent-soft: #e3ece4;
  --link: #1f4d38;
  --cran: #9b2a36;
  --name: #9b2a36;            /* the drawn name, written in red ink */
  --gold: #a8863f;            /* thin lines only */
  --twine-a: #f6efe1;
  --twine-b: #a3303b;
  --band: #8e2632;
  --band-edge: #6f1c26;
  --danger: #8f1f2a;
  --danger-soft: #f8e7e3;
  --warn-ink: #5a4100;
  --warn-soft: #f3e6c4;
  --focus: #9b2a36;
  --edge: rgba(98, 68, 34, 0.28);
  --shadow: rgba(74, 48, 20, 0.45);
  /* illustration */
  --i-pine: #2c5a45; --i-pine-dk: #224837; --i-dot: #f3ead8;
  --i-cream: #fbf7ee; --i-cream-shade: #e3d6bc; --i-cream-knot: #efe4cf;
  --i-kraft: #b8905f; --i-kraft-dk: #a47d4f; --i-fibre: #93703f;
  --i-cran: #942c38; --i-cran-dk: #76212b; --i-cran-stripe: #a4404b; --i-cran-knot: #85252f;
  --i-stem: #6b4a2b; --i-needle: #2d5c45; --i-needle2: #44775b;
  --i-holly: #2f5f47; --i-holly-vein: #558a6c; --i-berry: #a82a36; --i-berry-hi: #fbf7ee;
  --i-string: #7b5a38; --i-tag-line: #c9b594; --i-shadow: rgba(107, 74, 43, 0.18);
  --ground-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9 .6' numOctaves='2' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.38 0 0 0 0 0.26 0 0 0 0 0.12 0.9 0 0 0 -0.34'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9 .6' numOctaves='2' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.98 0 0 0 0 0.93 0 0 0 0 0.83 0 0.9 0 0 -0.36'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cfilter id='s' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='1.2' numOctaves='1' seed='23' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.3 0 0 0 0 0.2 0 0 0 0 0.1 0 0 3.2 0 -1.95'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23s)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%236b4a26' stroke-width='.7' stroke-linecap='round' opacity='0.22'/%3E%3Cpath d='M53.8 154.3Q58.2 152.9 61.4 151.1M123 254.4Q124.9 250.3 130.7 250.1M105.8 23.4Q100.1 25.4 92.2 27.9M218.9 246.4Q212.7 243.9 207.8 242.2M127.2 126.7Q121.3 127.1 114.3 125.6M226.4 216.4Q232.8 221.3 235.5 222.4M91.6 20.3Q85.9 23.4 78.3 22.8M201.5 53Q200.2 55.2 195.5 54.9M162.6 182.1Q170.6 184 178.1 182.8M69.3 175.8Q73.2 174.4 76.5 175.2M230.1 210.4Q220.9 211.2 214.9 213.4M235.8 0.3Q238.9 0.8 240.5 -1.9M44.3 54.3Q39.7 53 38.2 50.7M4.1 207.8Q0.2 208.3 -2.4 207.1M244.5 140.2Q238.8 139.9 231.1 138.8M25.7 11.6Q30.6 11.3 37.5 13.2M158.7 161.1Q164.3 164.8 173.5 167M104.1 202.7Q102.7 202.2 98 201.6M210.7 108.8Q206.1 107.3 198.3 102.9M48.7 184.2Q58 179.2 63.7 177.6M19.7 67.1Q11.7 61.7 5.5 58.7M7.6 120.3Q12 119.5 16.5 120.9' fill='none' stroke='%23f4e7cf' stroke-width='.7' stroke-linecap='round' opacity='0.45'/%3E%3C/svg%3E");
  --paper-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9 .6' numOctaves='2' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.38 0 0 0 0 0.26 0 0 0 0 0.12 0.55 0 0 0 -0.27'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9 .6' numOctaves='2' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.98 0 0 0 0 0.93 0 0 0 0 0.83 0 0.7 0 0 -0.32'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%236b4a26' stroke-width='.7' stroke-linecap='round' opacity='0.13'/%3E%3Cpath d='M53.8 154.3Q58.2 152.9 61.4 151.1M123 254.4Q124.9 250.3 130.7 250.1M105.8 23.4Q100.1 25.4 92.2 27.9M218.9 246.4Q212.7 243.9 207.8 242.2M127.2 126.7Q121.3 127.1 114.3 125.6M226.4 216.4Q232.8 221.3 235.5 222.4M91.6 20.3Q85.9 23.4 78.3 22.8M201.5 53Q200.2 55.2 195.5 54.9M162.6 182.1Q170.6 184 178.1 182.8M69.3 175.8Q73.2 174.4 76.5 175.2M230.1 210.4Q220.9 211.2 214.9 213.4M235.8 0.3Q238.9 0.8 240.5 -1.9M44.3 54.3Q39.7 53 38.2 50.7M4.1 207.8Q0.2 208.3 -2.4 207.1M244.5 140.2Q238.8 139.9 231.1 138.8M25.7 11.6Q30.6 11.3 37.5 13.2M158.7 161.1Q164.3 164.8 173.5 167M104.1 202.7Q102.7 202.2 98 201.6M210.7 108.8Q206.1 107.3 198.3 102.9M48.7 184.2Q58 179.2 63.7 177.6M19.7 67.1Q11.7 61.7 5.5 58.7M7.6 120.3Q12 119.5 16.5 120.9' fill='none' stroke='%23f4e7cf' stroke-width='.7' stroke-linecap='round' opacity='0.3'/%3E%3C/svg%3E");
  --brand-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 28'%3E%3Cpath d='M5 3.5C8 5 9.6 7.5 10 10.6' fill='none' stroke='%237b5a38' stroke-width='1.3' stroke-linecap='round'/%3E%3Cg transform='rotate(38 15 15)'%3E%3Cpath d='M6.5 11 10 7.5h13v15H10l-3.5-3.5Z' fill='%239b2a36'/%3E%3Ccircle cx='10.6' cy='15' r='1.9' fill='%23d5bc94'/%3E%3Cpath d='M14 12.5h6M14 17.5h4' stroke='%23e9b7bb' stroke-width='1.1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
  --twine-bow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 38'%3E%3Cg fill='none' stroke-width='3' stroke-linecap='round'%3E%3Cpath stroke='%23f6efe1' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3Cpath stroke='%23a3303b' stroke-dasharray='2.2 2.2' stroke-linecap='butt' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3C/g%3E%3Ccircle cx='32' cy='24' r='3.2' fill='%23a3303b'/%3E%3C/svg%3E");
  --tag-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 14'%3E%3Cpath d='M1 5 5 1h15.5v12H5L1 9Z' fill='%23e8d6b3' stroke='%239b2a36' stroke-width='1.2'/%3E%3Ccircle cx='5.4' cy='7' r='1.5' fill='%239b2a36'/%3E%3C/svg%3E");
  --radius: 4px;
  --serif: "Fraunces", "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Songti SC", "Noto Serif CJK SC", serif;
  --sans: "Figtree", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Noto Sans", sans-serif;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  color-scheme: light;
}

/* Dark: a pine-black ground with warm dark card stock on it; ribbon and twine
   stay as they are. Each tag's cut edge is traced so it never melts into the
   ground. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ground: #121a15; --paper: #121a15; --band-bg: #1b2821;
    --ground-ink: #efe6d6; --ground-muted: #c4b8a4;
    --tag: #352b22; --tag-2: #2b231c; --tag-edge: #6e5c48; --field: #251e18; --chip: #4a3c2d; --ring: #5b4b3b;
    --ink: #f1e9da; --muted: #c9bca8; --line: #4a3e32; --rule: #5a4b3c; --line-strong: #9a8a73;
    --accent: #2f6a4e; --accent-hover: #3a7a5c; --accent-ink: #fbf7ee; --accent-soft: #1f3228; --link: #a9d3b9;
    --cran: #e0857f; --name: #e0857f; --gold: #b99a5a; --twine-a: #d8ccb4; --twine-b: #b0434d; --band: #6e1f28; --band-edge: #521620;
    --danger: #f0a3a8; --danger-soft: #3a1c1f; --warn-ink: #f0d492; --warn-soft: #362b14; --focus: #e0857f;
    --edge: rgba(0, 0, 0, 0.55); --shadow: rgba(0, 0, 0, 0.7);
    --i-pine: #2a5140; --i-pine-dk: #1f3e31; --i-dot: #d9ccb4;
    --i-cream: #e7dcc6; --i-cream-shade: #c7b899; --i-cream-knot: #d6c9ae;
    --i-kraft: #8f7049; --i-kraft-dk: #7b5f3d; --i-fibre: #6d5433;
    --i-cran: #862f39; --i-cran-dk: #68222b; --i-cran-stripe: #963f49; --i-cran-knot: #74262f;
    --i-stem: #8a6a48; --i-needle: #3f7a5c; --i-needle2: #5b9073;
    --i-holly: #3a6f54; --i-holly-vein: #5f967a; --i-berry: #c0404c; --i-berry-hi: #f3e9d6;
    --i-string: #a88963; --i-tag-line: #b3a283; --i-shadow: rgba(0, 0, 0, 0.35);
    --ground-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.72 0 0 0 0 0.78 0 0 0 0 0.68 0.42 0 0 0 -0.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -0.4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%23a8b9a4' stroke-width='.7' stroke-linecap='round' opacity='0.1'/%3E%3C/svg%3E");
    --paper-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.72 0 0 0 0 0.78 0 0 0 0 0.68 0.42 0 0 0 -0.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -0.4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%23a8b9a4' stroke-width='.7' stroke-linecap='round' opacity='0.1'/%3E%3C/svg%3E");
    --brand-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 28'%3E%3Cpath d='M5 3.5C8 5 9.6 7.5 10 10.6' fill='none' stroke='%23a88963' stroke-width='1.3' stroke-linecap='round'/%3E%3Cg transform='rotate(38 15 15)'%3E%3Cpath d='M6.5 11 10 7.5h13v15H10l-3.5-3.5Z' fill='%23c9505b'/%3E%3Ccircle cx='10.6' cy='15' r='1.9' fill='%23121a15'/%3E%3Cpath d='M14 12.5h6M14 17.5h4' stroke='%23f0c4c7' stroke-width='1.1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
    --twine-bow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 38'%3E%3Cg fill='none' stroke-width='3' stroke-linecap='round'%3E%3Cpath stroke='%23d8ccb4' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3Cpath stroke='%23b0434d' stroke-dasharray='2.2 2.2' stroke-linecap='butt' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3C/g%3E%3Ccircle cx='32' cy='24' r='3.2' fill='%23b0434d'/%3E%3C/svg%3E");
    --tag-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 14'%3E%3Cpath d='M1 5 5 1h15.5v12H5L1 9Z' fill='%234a3c2d' stroke='%23e0857f' stroke-width='1.2'/%3E%3Ccircle cx='5.4' cy='7' r='1.5' fill='%23e0857f'/%3E%3C/svg%3E");
    color-scheme: dark;
  }
}

/* The same dark values when the page is told to be dark. */
:root[data-theme="dark"] {
    --ground: #121a15; --paper: #121a15; --band-bg: #1b2821;
    --ground-ink: #efe6d6; --ground-muted: #c4b8a4;
    --tag: #352b22; --tag-2: #2b231c; --tag-edge: #6e5c48; --field: #251e18; --chip: #4a3c2d; --ring: #5b4b3b;
    --ink: #f1e9da; --muted: #c9bca8; --line: #4a3e32; --rule: #5a4b3c; --line-strong: #9a8a73;
    --accent: #2f6a4e; --accent-hover: #3a7a5c; --accent-ink: #fbf7ee; --accent-soft: #1f3228; --link: #a9d3b9;
    --cran: #e0857f; --name: #e0857f; --gold: #b99a5a; --twine-a: #d8ccb4; --twine-b: #b0434d; --band: #6e1f28; --band-edge: #521620;
    --danger: #f0a3a8; --danger-soft: #3a1c1f; --warn-ink: #f0d492; --warn-soft: #362b14; --focus: #e0857f;
    --edge: rgba(0, 0, 0, 0.55); --shadow: rgba(0, 0, 0, 0.7);
    --i-pine: #2a5140; --i-pine-dk: #1f3e31; --i-dot: #d9ccb4;
    --i-cream: #e7dcc6; --i-cream-shade: #c7b899; --i-cream-knot: #d6c9ae;
    --i-kraft: #8f7049; --i-kraft-dk: #7b5f3d; --i-fibre: #6d5433;
    --i-cran: #862f39; --i-cran-dk: #68222b; --i-cran-stripe: #963f49; --i-cran-knot: #74262f;
    --i-stem: #8a6a48; --i-needle: #3f7a5c; --i-needle2: #5b9073;
    --i-holly: #3a6f54; --i-holly-vein: #5f967a; --i-berry: #c0404c; --i-berry-hi: #f3e9d6;
    --i-string: #a88963; --i-tag-line: #b3a283; --i-shadow: rgba(0, 0, 0, 0.35);
    --ground-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.72 0 0 0 0 0.78 0 0 0 0 0.68 0.42 0 0 0 -0.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -0.4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%23a8b9a4' stroke-width='.7' stroke-linecap='round' opacity='0.1'/%3E%3C/svg%3E");
    --paper-tex: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256'%3E%3Cfilter id='f' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='5' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.72 0 0 0 0 0.78 0 0 0 0 0.68 0.42 0 0 0 -0.2'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23f)'/%3E%3Cfilter id='h' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' seed='17' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 -0.4'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23h)'/%3E%3Cpath d='M0 235.7Q6.8 233.3 13.3 232.3M192.5 193.3Q187.5 191.9 179.9 192.6M95.8 181.2Q102.1 184.5 108.6 184.3M206.7 31.4Q200.6 31.7 193.4 31.2M233.5 232.5Q240.2 230 248.3 230.2M76.2 109.7Q71.4 112.6 64.9 112.5M15 70Q8.8 71.3 5 69.3M14 93.6Q6.2 93.7 -1.8 96.6M103.8 72.6Q108.4 72.3 112.7 71.1M59.7 232.1Q53.9 232.4 47.1 232.7M129.3 176.4Q134.1 180.1 140.9 183.2M89.8 84.6Q80.5 86.9 74.4 86.7M19.9 104.1Q26.5 101.2 35.4 97.3M36.9 117Q46.4 119.5 52.9 118.8M226.6 232.4Q228 231.5 231.5 234M0.4 157.9Q-4 158.6 -9.9 161.4M225.8 60.2Q222.6 58.7 219.5 61.2M233.7 163.1Q239.4 168.8 247.5 170.7M144.7 173.9Q148.6 171.1 151.9 171.8M197 179.4Q198 181.7 202.2 180.8M33.5 176.1Q41.9 181.6 47.4 183.2M244.3 195.8Q252.7 194.7 258 194.5M60.1 103.7Q56.5 102.5 51.9 99.5M85.8 185.7Q92.1 187.2 94.5 184.8M161.9 223.3Q166 226.3 173.1 229.4M142.7 197.5Q145.6 198 148.9 201.2M169.6 133.6Q162.1 134 155.6 132.5M6.7 76.5Q12.7 75.8 20.3 77.2M168.9 109.9Q164 115.1 155.9 117.1M174.3 245.5Q170.1 250.4 164 252.1M9.5 34.8Q10.1 33.8 14.7 31.9M242.1 49.2Q247 46.2 254 43.6M254.5 108.2Q249.3 105.4 244.9 106.2M58.9 206.8Q65.7 209.6 72.5 215.4' fill='none' stroke='%23a8b9a4' stroke-width='.7' stroke-linecap='round' opacity='0.1'/%3E%3C/svg%3E");
    --brand-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 28 28'%3E%3Cpath d='M5 3.5C8 5 9.6 7.5 10 10.6' fill='none' stroke='%23a88963' stroke-width='1.3' stroke-linecap='round'/%3E%3Cg transform='rotate(38 15 15)'%3E%3Cpath d='M6.5 11 10 7.5h13v15H10l-3.5-3.5Z' fill='%23c9505b'/%3E%3Ccircle cx='10.6' cy='15' r='1.9' fill='%23121a15'/%3E%3Cpath d='M14 12.5h6M14 17.5h4' stroke='%23f0c4c7' stroke-width='1.1' stroke-linecap='round'/%3E%3C/g%3E%3C/svg%3E");
    --twine-bow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 38'%3E%3Cg fill='none' stroke-width='3' stroke-linecap='round'%3E%3Cpath stroke='%23d8ccb4' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3Cpath stroke='%23b0434d' stroke-dasharray='2.2 2.2' stroke-linecap='butt' d='M32 24C20 5 4 7 9.5 17.5 13 24 25 25 32 24M32 24C44 5 60 7 54.5 17.5 51 24 39 25 32 24M32 24C28 30 23.5 33 18.5 36.5M32 24C36 30 40.5 33 45.5 36.5'/%3E%3C/g%3E%3Ccircle cx='32' cy='24' r='3.2' fill='%23b0434d'/%3E%3C/svg%3E");
    --tag-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 14'%3E%3Cpath d='M1 5 5 1h15.5v12H5L1 9Z' fill='%234a3c2d' stroke='%23e0857f' stroke-width='1.2'/%3E%3Ccircle cx='5.4' cy='7' r='1.5' fill='%23e0857f'/%3E%3C/svg%3E");
    color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
/* Tool pages: the tool re-renders the stored list and links above the static
   body text after the page loads, so the page grows by up to ~1,900 px. WebKit's
   scroll anchoring then moved Back from a card (/r/) to the wrong place on /
   (scrollY 5165 instead of 3260 at 390 x 844, 2026-09-27). The page restores
   its own scroll position, so anchoring is off there. */
html:has(> body.has-tool) { overflow-anchor: none; }

body {
  /* Pages sit on a pale sheet, so the tags stand out and long pages don't feel
     heavy; the page that opens a link (/r/) sits on kraft. A punched hole shows
     whichever is behind. */
  --page: var(--paper);
  --page-tex: var(--paper-tex);
  margin: 0;
  background: var(--page-tex) 0 0 / 240px 240px, var(--page);
  color: var(--ground-ink);
  /* 1rem, not 16px: a larger default text size set in the browser must reach
     the labels, buttons, fields and the card, not only the rem-sized headings. */
  font: 1rem/1.55 var(--sans);
  /* Safari/iOS before 15.4 ignore overflow-wrap: anywhere; break-word is the
     older spelling of the same thing, so long one-word names still wrap there. */
  word-break: break-word;
  overflow-wrap: anywhere;
}
body.reveal-page { --page: var(--ground); --page-tex: var(--ground-tex); }
/* On the link page nothing shows until the script has picked the card, so
   the line and footer under it would jump down a moment later, on every link
   a person opens. Kept in place but unpainted until then. */
body.reveal-page:not([data-view]) .aside, body.reveal-page:not([data-view]) footer.site { visibility: hidden; }
@media (scripting: none) {
  body.reveal-page:not([data-view]) .aside, body.reveal-page:not([data-view]) footer.site { visibility: visible; }
}

/* The draw tool and the link page show their controls from the first paint;
   with scripting off they would do nothing, so the noscript message stands
   alone. (Where the script fails to start, src/boot.js does the same.) */
@media (scripting: none) {
  .app-body { display: none !important; }
}

.wrap { max-width: 42rem; margin: 0 auto; padding: 0 16px; }

a { color: var(--link); text-underline-offset: 3px; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

h1, h2, h3, h4 { font-family: var(--serif); font-weight: 600; line-height: 1.15; margin: 0 0 0.5rem; }
h1 { font-size: clamp(2rem, 7.2vw, 3rem); letter-spacing: -0.015em; }
h2 { font-size: 1.4rem; letter-spacing: -0.005em; }
h3 { font-size: 1.15rem; margin-top: 1.25rem; }
h4 { font-size: 1.1rem; margin-top: 1.1rem; }
p { margin: 0 0 0.75rem; }

/* ---------- header and footer ---------- */

/* The header: the brand, then the six links. A phone gives the links a row of
   their own that scrolls sideways inside itself, never the page. */
header.site {
  position: relative; z-index: 1;
  background: var(--ground-tex) 0 0 / 240px 240px, var(--band-bg);
  border-bottom: 1px solid var(--edge);
}
.site-bar { display: flex; flex-wrap: wrap; align-items: center; column-gap: 16px; }
.brand {
  display: inline-flex; align-items: center; gap: 8px; min-height: 48px;
  font-family: var(--serif); font-weight: 600; font-size: 1.15rem; letter-spacing: -0.01em;
  color: var(--ground-ink); text-decoration: none;
}
.brand::before {
  content: ""; width: 26px; height: 26px; flex: none;
  background: var(--brand-mark) center / contain no-repeat;
}
.brand:hover { color: var(--ground-ink); text-decoration: underline; text-decoration-thickness: 1px; }
.site-nav { flex: 1 1 100%; min-width: 0; margin: 0 -16px; }
.site-nav ul {
  list-style: none; margin: 0; padding: 0 16px 6px; display: flex; gap: 2px 18px;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.site-nav ul::-webkit-scrollbar { display: none; }
.site-nav li { flex: none; }
.site-nav a {
  display: inline-flex; align-items: center; min-height: 36px; white-space: nowrap;
  color: var(--ground-ink); font-weight: 600; font-size: 0.95rem; text-decoration: none;
  border-bottom: 2px solid transparent;
}
.site-nav a:hover { border-bottom-color: var(--ground-ink); }
.site-nav a[aria-current="page"] { border-bottom-color: var(--cran); }
@media (min-width: 900px) {
  .brand { white-space: nowrap; }
  .site-bar { flex-wrap: nowrap; max-width: 72rem; }
  .site-nav { flex: 1 1 auto; margin: 0; }
  .site-nav ul { justify-content: flex-end; padding: 0; overflow: visible; }
  .site-nav a { min-height: 48px; }
}
.skip {
  position: absolute; left: 8px; top: -60px; z-index: 10;
  background: var(--tag); color: var(--ink); padding: 8px 14px; border-radius: var(--radius);
  border: 1.5px solid var(--ink); font-weight: 600;
}
.skip:focus { top: 8px; }

/* main.wrap: a bare main lost to .wrap's padding, so headings sat flush against
   the header and a card's top margin collapsed through main (the page moved
   down as the card replaced "Loading"). */
main.wrap { padding-top: 24px; padding-bottom: 40px; }


/* ---------- the page head: a band of kraft paper ---------- */

/* Every page opens on a band of kraft with its breadcrumbs, H1 and lede. The
   band is the full width of the window; the text keeps to the column. */
.page-head {
  position: relative; z-index: 0;
  background: var(--ground-tex) 0 0 / 240px 240px, var(--band-bg);
  border-bottom: 1px solid var(--edge);
  padding: 14px 0 20px;
}
.page-head h1 { text-align: center; margin: 0.2rem auto 0.5rem; color: var(--ground-ink); text-wrap: balance; max-width: 40rem; }
.lede {
  color: var(--ground-muted); font-size: 1.05rem; max-width: 34rem;
  text-align: center; margin: 0 auto 0.5rem; text-wrap: pretty;
}
.page-head .lede { margin-bottom: 0; text-wrap: balance; }
/* A tool page's title sits a little tighter: its name field belongs on a
   phone's first screen, just under the lede. */
.page-head-tool { padding: 16px 0 16px; }
.page-head-tool h1 { font-size: clamp(1.75rem, 7vw, 3rem); }
.page-head-tool .lede { font-size: 1rem; line-height: 1.5; }
@media (min-width: 480px) {
  .page-head { padding-bottom: 26px; }
}
@media (min-width: 720px) {
  .page-head { padding: 22px 0 34px; }
  .page-head-tool h1 { font-size: 3rem; letter-spacing: -0.02em; }
  .lede, .page-head-tool .lede { font-size: 1.15rem; }
}

/* Breadcrumbs: small, on the band, above the H1. */
.crumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; justify-content: center; gap: 0 6px; font-size: 0.88rem; color: var(--ground-muted); }
.crumbs li + li::before { content: "/"; margin-right: 6px; color: var(--ground-muted); }
.crumbs a { color: var(--ground-ink); }
.crumbs [aria-current] { color: var(--ground-muted); }

/* The four steps: small card tags, each cut to a point at its left end round
   a punched hole, numbered like the steps. They sit in step 1 under the name
   field (so the field is on a phone's first screen), with Try an example
   first. Two to a row on a phone, four on a wide screen. */
.intro { margin: 14px 0 0.75rem; padding-top: 12px; border-top: 1px dashed var(--rule); }
.intro-h {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  margin: 14px 0 10px; color: var(--ink);
  font: 700 1.02rem/1.3 var(--sans); letter-spacing: 0.16em; font-variant-caps: all-small-caps;
}
.intro-h::before, .intro-h::after { content: ""; height: 1px; width: 2.2rem; background: var(--gold); }
.strip {
  list-style: none; margin: 0; padding: 0; counter-reset: strip;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px;
}
.strip li {
  --cut: 12px;
  counter-increment: strip;
  position: relative; min-width: 0;
  padding: 8px 10px 9px 26px;
  border: 1px solid transparent; border-radius: 0 4px 4px 0;
  color: var(--ink);
  background:
    radial-gradient(circle at 12px 50%, var(--tag) 0 2.7px, var(--edge) 3px 3.6px, var(--ring) 3.8px 5.8px, transparent 6.1px) padding-box,
    linear-gradient(135deg, transparent calc((var(--cut) - 0.6px) * 0.7071), var(--tag-2) 0) left top / 100% 51% no-repeat padding-box,
    linear-gradient(45deg, transparent calc((var(--cut) - 0.6px) * 0.7071), var(--tag-2) 0) left bottom / 100% 51% no-repeat padding-box,
    linear-gradient(135deg, transparent calc(var(--cut) * 0.7071), var(--tag-edge) 0) left top / 100% 51% no-repeat border-box,
    linear-gradient(45deg, transparent calc(var(--cut) * 0.7071), var(--tag-edge) 0) left bottom / 100% 51% no-repeat border-box;
  filter: drop-shadow(0 1px 0 var(--edge));
}
/* The number, stamped like the steps' own, set into the title's first line;
   whatever wraps runs the tag's full width under it, so large text never
   squeezes a word into a column beside it. Our own few words, so a word that
   doesn't fit by the number goes under it whole instead of breaking. */
.strip-t { display: block; font: 600 1.02rem/1.4 var(--serif); letter-spacing: -0.005em; overflow-wrap: normal; word-break: normal; }
.strip-t::before {
  content: counter(strip); content: counter(strip) / "";
  float: left; margin: 0.05rem 7px 0 0;
  display: grid; place-items: center;
  width: 1.3rem; height: 1.3rem; border-radius: 50%;
  border: 1.5px solid var(--cran); color: var(--cran);
  box-shadow: inset 0 0 0 1.5px var(--tag-2), inset 0 0 0 2.5px var(--cran);
  font: 600 0.72rem/1 var(--serif); letter-spacing: 0;
}
.strip-opt {
  display: block; font: 600 0.9rem/1.2 var(--sans); color: var(--muted);
  letter-spacing: 0.08em; font-variant-caps: all-small-caps;
}
.strip-d { display: block; margin-top: 3px; color: var(--muted); font-size: 0.88rem; line-height: 1.35; text-wrap: pretty; }
/* Two to a row at every width: the tags sit inside the step's own tag, and
   four across that column squeezed each title onto two lines. */
.intro-more {
  margin: 12px auto 0; max-width: 32rem; text-align: center; text-wrap: balance;
  color: var(--muted); font-size: 0.95rem;
}
.intro-more a { font-weight: 600; }

/* Try an example; once it's on the page, what it is and how to clear it.
   The bar is a sheet laid on the card with a dashed edge, like the rules'
   placeholder, and stamped Example. */
.example-try {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px 12px;
  margin: 0; text-align: center;
}
.example-try p { margin: 0; color: var(--muted); font-size: 0.92rem; text-wrap: balance; }
.example-bar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px 14px;
  margin: 0; padding: 10px 12px 10px 14px;
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--tag); color: var(--ink);
}
/* No text-wrap: pretty here: WebKit balances the lines, leaving a quarter of the box empty. */
.example-bar p { margin: 0; flex: 1 1 16rem; font-size: 0.95rem; }
.example-bar button { flex: none; }
.example-note { margin: 0.9rem 0 0.25rem; background: var(--tag-2); }
.stamp {
  display: inline-block; margin-right: 4px; padding: 0 7px; vertical-align: 0.05em;
  border: 1.5px solid var(--cran); border-radius: 3px; color: var(--cran);
  font: 700 0.9rem/1.35 var(--sans); letter-spacing: 0.1em; font-variant-caps: all-small-caps;
}
.optional.example-mark { color: var(--cran); border-color: var(--cran); }

/* ---------- step tags: card stock threaded on twine ---------- */

/* A tag with its top corners cut off, drawn by the background rather than
   clip-path so the twine above and focus rings near the edge are never cut.
   The border-box layers trace a 1px cut edge; the card sits 1px inside it. */
.panel, .card {
  border: 1px solid transparent;
  background:
    linear-gradient(135deg, transparent calc((var(--cut) - 0.6px) * 0.7071), var(--tag) 0) left top / 51% 100% no-repeat padding-box,
    linear-gradient(225deg, transparent calc((var(--cut) - 0.6px) * 0.7071), var(--tag) 0) right top / 51% 100% no-repeat padding-box,
    linear-gradient(135deg, transparent calc(var(--cut) * 0.7071), var(--tag-edge) 0) left top / 51% 100% no-repeat border-box,
    linear-gradient(225deg, transparent calc(var(--cut) * 0.7071), var(--tag-edge) 0) right top / 51% 100% no-repeat border-box;
}

.panel {
  --cut: 20px;
  --hole-y: 25px;
  --gap: 30px;
  position: relative;
  color: var(--ink);
  border-radius: 0 0 6px 6px;
  box-shadow: 0 1px 0 var(--edge), 0 14px 22px -18px var(--shadow);
  padding: 50px 16px 22px;
  margin: var(--gap) 0 0;
}
@media (min-width: 560px) { .panel { --gap: 44px; padding: 56px 28px 28px; } }
/* reinforcement ring and punched hole, showing the page through */
.panel::after {
  content: ""; position: absolute; z-index: 0;
  top: calc(var(--hole-y) - 12px); left: 50%; width: 24px; height: 24px; margin-left: -12px;
  border-radius: 50%;
  background: radial-gradient(circle closest-side, var(--page) 0 44%, var(--edge) 46% 52%, var(--ring) 54% 100%);
}
/* the twine: comes down from the tag above and goes in through the hole */
.panel::before {
  content: ""; position: absolute; z-index: 1;
  top: calc(var(--gap) * -1 - 1px); left: 50%; width: 3px; margin-left: -1.5px;
  height: calc(var(--gap) + var(--hole-y) + 1px);
  border-radius: 2px;
  background: repeating-linear-gradient(-58deg, var(--twine-b) 0 1.6px, var(--twine-a) 1.6px 3.4px);
}
/* the first tag hangs from a twine bow, just under the kraft band */
.panel:first-of-type { --gap: 52px; }
.panel:first-of-type::before {
  top: calc(var(--gap) * -1 + 8px); width: 64px; margin-left: -32px; height: calc(var(--gap) - 8px + var(--hole-y));
  border-radius: 0;
  background:
    var(--twine-bow) center top / 64px 38px no-repeat,
    repeating-linear-gradient(-58deg, var(--twine-b) 0 1.6px, var(--twine-a) 1.6px 3.4px) center 24px / 3px calc(100% - 24px) no-repeat;
}
@media (min-width: 560px) { .panel:first-of-type { --gap: 64px; } }

/* the step number hangs in the margin like a stamped number, so a long
   heading wraps under its own first word */
.tool .panel > h3 { position: relative; padding-left: 2.75rem; min-height: 2rem; padding-top: 0.2rem; margin: 0 0 0.75rem; font-size: 1.4rem; letter-spacing: -0.005em; }
.tool .panel > h3:focus { outline: none; }
.tool .panel > h3:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.step {
  position: absolute; left: 0; top: 0;
  display: grid; place-items: center;
  width: 2rem; height: 2rem;
  border-radius: 50%; border: 1.5px solid var(--cran); color: var(--cran);
  box-shadow: inset 0 0 0 2px var(--tag), inset 0 0 0 3px var(--cran);
  font: 600 0.95rem/1 var(--serif);
}
.count { font-family: var(--sans); font-weight: 500; color: var(--muted); font-size: 1rem; margin-left: 0.2rem; }
.optional {
  font-family: var(--sans); font-weight: 600; color: var(--muted); font-size: 0.95rem;
  letter-spacing: 0.08em; font-variant-caps: all-small-caps;
  border: 1px solid var(--rule); border-radius: 999px; padding: 0 8px; line-height: 1.45;
  display: inline-block; vertical-align: 0.2em; margin-left: 0.35rem; white-space: nowrap;
}

label { display: block; font-weight: 600; margin: 0 0 0.3rem; }
label.check { display: flex; gap: 0.5rem; align-items: flex-start; font-weight: 400; margin: 0.75rem 0; }
label.check input { width: 1.15rem; height: 1.15rem; margin: 0.2rem 0 0; accent-color: var(--accent); flex: none; }

.help { color: var(--muted); font-size: 0.92rem; }
.inline + .help { margin-top: 0.5rem; }
.field { margin-bottom: 0.75rem; min-width: 0; }

input[type="text"], input[type="date"], select, textarea {
  width: 100%;
  min-height: 46px;
  font: inherit;
  color: var(--ink);
  background: var(--field);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  padding: 8px 12px;
  max-width: 100%;
}
input[type="text"]:hover, select:hover, textarea:hover { border-color: var(--ink); }
textarea { resize: vertical; line-height: 1.45; }
/* Each browser's own placeholder grey fell below 4.5:1 (2.4:1 in WebKit on
   white, 3.7:1 in Chromium's dark field), and "For example, $30" is the only
   example of what to type. The muted text colour reads in both themes. */
::placeholder { color: var(--muted); opacity: 1; }
/* A drop-down looks like the name field plus a drawn chevron, in every engine
   and both themes. The browser's own arrow was faint and differed per engine,
   so the field read as a text box. The wrapper draws the chevron, since a
   select can't hold a pseudo-element. */
.select { position: relative; display: block; min-width: 0; }
.select select {
  appearance: none; -webkit-appearance: none;
  padding: 10px 38px 10px 12px; line-height: 24px;
  text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
  cursor: pointer;
}
.select::after {
  content: ""; position: absolute; pointer-events: none;
  right: 15px; top: 50%; width: 8px; height: 8px; margin-top: -6px;
  border-right: 2px solid var(--ink); border-bottom: 2px solid var(--ink);
  transform: rotate(45deg);
}
/* The same ring the name field shows, whether reached by keyboard or clicked. */
.select select:focus { outline: 3px solid var(--focus); outline-offset: 2px; }
.select select.unset { color: var(--muted); }
.select select option { color: var(--ink); background: var(--field); }
input:disabled, select:disabled { opacity: 0.6; }

button {
  font: inherit; font-weight: 600;
  min-height: 46px; padding: 8px 18px;
  border-radius: var(--radius);
  border: 1.5px solid var(--line-strong);
  background: var(--field); color: var(--ink);
  cursor: pointer;
}
button:hover { border-color: var(--ink); background: var(--tag-2); }
button:disabled { opacity: 0.55; cursor: not-allowed; }
/* One solid pine fill, in both themes. */
button.primary {
  background: var(--accent); border-color: var(--accent); color: var(--accent-ink);
  padding-left: 22px; padding-right: 22px;
}
button.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent-hover); }
/* Not ready yet rather than broken: an outline on the card, the label still
   readable, and the line above it says what is missing. */
button.primary:disabled { background: transparent; border-color: var(--rule); color: var(--muted); opacity: 1; }
button.quiet {
  border-color: transparent; background: transparent; color: var(--link);
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px;
  padding-left: 8px; padding-right: 8px;
}
button.quiet:hover { background: transparent; border-color: transparent; text-decoration-thickness: 2px; }
button.small { min-height: 36px; font-weight: 500; }

.inline { display: flex; gap: 8px; }
.inline input { flex: 1 1 auto; min-width: 0; }
.inline button { flex: none; }

.grid2 { display: grid; gap: 0 14px; grid-template-columns: 1fr; }
@media (min-width: 480px) { .grid2 { grid-template-columns: 1fr 1fr; } }

details { margin: 0.25rem 0 0.75rem; }
summary { cursor: pointer; color: var(--link); font-weight: 600; min-height: 32px; padding: 4px 0; width: fit-content; }
.paste-body { margin-top: 0.5rem; display: grid; gap: 0.5rem; }
.paste-body label, .paste-body .help { margin: 0; }
.paste-body button { justify-self: start; }

/* Empty, a message area takes no room but stays rendered: a live region that
   appears together with its first message is not announced (display: none
   kept it out of the accessibility tree until then). */
.feedback:empty { margin: 0; }
.feedback { margin: 0.5rem 0; font-size: 0.95rem; }
.feedback p { margin: 0 0 0.35rem; }
.warn-text { color: var(--warn-ink); background: var(--warn-soft); border-radius: var(--radius); padding: 6px 10px; }
.field-msg { margin: 6px 0 0; font-size: 0.92rem; }

/* The paste preview: pasted names wait here, one editable row each, until Add. */
.preview {
  border: 1px solid var(--rule); border-radius: var(--radius);
  background: var(--tag-2); padding: 14px 12px; margin: 0.75rem 0;
}
@media (min-width: 560px) { .preview { padding: 16px; } }
.preview h4 { margin-top: 0; }
.preview h4:focus { outline: none; }
.preview h4:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.preview-notes p { color: var(--muted); font-size: 0.92rem; margin: 0 0 0.35rem; }
.preview-rows { list-style: none; margin: 0.5rem 0; padding: 0; }
.prow { border-top: 1px solid var(--rule); padding: 8px 0; }
.prow:last-child { border-bottom: 1px solid var(--rule); }
.prow-main { display: flex; align-items: center; gap: 4px; }
.prow-main input { flex: 1 1 auto; min-width: 0; }
.prow-main input[aria-invalid="true"] { border-color: var(--warn-ink); }
.prow-main .chip-x { width: 44px; min-height: 44px; margin-left: 0; }
.prow-note p { margin: 6px 0 0; font-size: 0.9rem; }
.prow-note .with { color: var(--muted); }
.preview-left { margin: 0.75rem 0 0; }
.preview-left-list { list-style: none; margin: 0.35rem 0 0; padding: 0; }
.pleft {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 0 8px;
  border-top: 1px solid var(--rule); padding: 4px 0;
}
.pleft:last-child { border-bottom: 1px solid var(--rule); }
.pleft-main { display: flex; flex-direction: column; min-width: 0; }
.pleft-kind { color: var(--muted); font-size: 0.85rem; }
.pleft button { padding-right: 0; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* Each person is a small kraft tag with a punched hole. Names are set in the
   sans everywhere on this page (tags, rules, links); the serif is for headings. */
.people { list-style: none; margin: 0.9rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; }
.people li {
  display: inline-flex; align-items: center; max-width: 100%; min-height: 34px;
  padding: 1px 1px 1px 21px;
  border-radius: 0 4px 4px 0;
  background:
    radial-gradient(circle at 9.5px 50%, var(--tag) 0 2.6px, var(--edge) 2.9px 3.4px, transparent 3.6px),
    linear-gradient(135deg, transparent 7.8px, var(--chip) 0) left top / 100% 51% no-repeat,
    linear-gradient(45deg, transparent 7.8px, var(--chip) 0) left bottom / 100% 51% no-repeat;
  color: var(--ink);
}
.chip-name { min-width: 0; font-weight: 500; }
.chip-x {
  min-height: 32px; width: 32px; padding: 0; margin-left: 1px; flex: none;
  border-radius: 50%; border-color: transparent; background: transparent;
  color: var(--muted); font-size: 1.2rem; line-height: 1;
}
.chip-x:hover { color: var(--danger); border-color: transparent; background: rgba(0, 0, 0, 0.06); }
/* two short names to a row on the narrowest phones */
@media (max-width: 359px) {
  .people { gap: 6px; }
  .people li { padding-left: 18px; font-size: 0.95rem; background:
    radial-gradient(circle at 8px 50%, var(--tag) 0 2.4px, var(--edge) 2.7px 3.2px, transparent 3.4px),
    linear-gradient(135deg, transparent 6.8px, var(--chip) 0) left top / 100% 51% no-repeat,
    linear-gradient(45deg, transparent 6.8px, var(--chip) 0) left bottom / 100% 51% no-repeat; }
  .people .chip-x { width: 28px; }
}
.empty { color: var(--muted); margin: 0.75rem 0 0; font-style: italic; font-family: var(--serif); font-weight: 400; }

.rules { list-style: none; margin: 0.75rem 0 0; padding: 0; }
.rules li {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px;
  border-top: 1px solid var(--rule); padding: 6px 0;
}
.rules li:last-child { border-bottom: 1px solid var(--rule); }
.rule-text { min-width: 0; flex: 1 1 14rem; }
/* On a narrow phone Remove wraps under its rule. Pulled back by its border
   and padding, its word then starts on the rule's left edge, not 9.5px in. */
.rules li > button.quiet { margin-inline-start: -9.5px; }

/* Step 2 before there are two people: what to do first, in place of fields
   that could only sit there switched off. A dashed slot on the card, where
   the rule fields will appear. */
.step-wait {
  border: 1px dashed var(--line-strong); border-radius: var(--radius);
  background: var(--tag-2); color: var(--muted);
  padding: 12px 14px; margin: 0.25rem 0 0;
}
.step-wait p { margin: 0; text-wrap: pretty; }
.step-wait p + p { margin-top: 0.4rem; }
.step-wait strong { color: var(--ink); font-weight: 600; }

/* Phones: each label over its own field, one column, the same gaps as step 1. */
.rule-form { margin-top: 0.25rem; }
.rule-form .select { margin-bottom: 0.75rem; }
.rule-form .rule-both { margin: 0 0 0.75rem; }
.rule-why { margin: 0.5rem 0 0; font-size: 0.92rem; color: var(--muted); }
/* Not ready yet rather than broken: an outline, the label still readable, and
   the line under it says what is missing. */
#excl-add:disabled, #excl-add:disabled:hover {
  opacity: 1; background: transparent; border-color: var(--rule); color: var(--muted);
}
/* Wide: one sentence, "[Anna] shouldn't give to [Ben] [Add rule]", with the
   both-ways box and the line about the button under it. The first field's
   label is left to screen readers there; the sentence and the field's
   "Choose a name" say what it is. */
@media (min-width: 720px) {
  .rule-form {
    display: grid; align-items: center; column-gap: 12px;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
  }
  .rule-form .rule-a {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }
  .rule-form .select { margin: 0; }
  .rule-sa { grid-area: 1 / 1; }
  .rule-form .rule-b { grid-area: 1 / 2; margin: 0; font-weight: 500; white-space: nowrap; }
  .rule-form .rule-b::first-letter { text-transform: lowercase; }
  .rule-sb { grid-area: 1 / 3; }
  #excl-add { grid-area: 1 / 4; }
  .rule-form .rule-both { grid-area: 2 / 1 / 3 / -1; margin: 0.75rem 0 0; }
  .rule-why { grid-area: 3 / 1 / 4 / -1; margin-top: 0.4rem; }
}

.alert {
  border: 1px solid var(--danger); background: var(--danger-soft); color: var(--ink);
  border-radius: var(--radius); padding: 12px 14px; margin: 0.75rem 0;
}
.alert p:last-child { margin-bottom: 0; }
.alert-title { font-weight: 700; color: var(--danger); }
#stale-note { border-color: var(--warn-ink); background: var(--warn-soft); }
.notice { border: 1px solid var(--rule); background: var(--warn-soft); color: var(--warn-ink); border-radius: var(--radius); padding: 10px 14px; }
.tool .app-body > [role="status"] .notice { margin: 1rem auto 0; max-width: 34rem; }

.actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 0.75rem; }
.actions.end { justify-content: flex-end; margin-top: 1.25rem; }

#draw-btn { min-height: 52px; padding: 10px 28px; }
@media (max-width: 479px) { #draw-btn { width: 100%; } }

/* results: one small tag per person */
#results { margin-top: 1.5rem; border-top: 1px solid var(--rule); padding-top: 1.1rem; }
#results h4:focus { outline: none; }
#results h4:focus-visible { outline: 3px solid var(--focus); }
#results > h4 { margin-top: 0; font-size: 1.3rem; }
.meta { color: var(--muted); font-size: 0.95rem; }
.meta strong {
  color: var(--cran); font-family: var(--mono); letter-spacing: 0.08em; font-size: 0.9rem;
  border: 1.5px solid var(--cran); border-radius: 3px; padding: 1px 6px;
}
h4.sub { font-size: 1.05rem; font-family: var(--sans); font-weight: 700; margin-top: 1.6rem; }
#forgotten h4:focus { outline: none; }
#forgotten h4:focus-visible { outline: 3px solid var(--focus); }

.links { list-style: none; margin: 0.9rem 0 0; padding: 0; }
.links li { border-top: 1px solid var(--rule); padding: 10px 0; }
.links li:last-child { border-bottom: 1px solid var(--rule); }
.link-head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 6px 12px; }
.who { font-weight: 600; min-width: 0; flex: 1 1 8rem; }
.who::before {
  content: ""; display: inline-block; width: 22px; height: 14px; margin-right: 8px; vertical-align: -1px;
  background: var(--tag-icon) center / contain no-repeat;
}
.link-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.link-actions button { min-width: 6.5rem; }
/* Wide enough for "Copy link", "Copied" and "Not copied", so the label swap never reflows the row. */
.link-actions button.copy { min-width: 7.5rem; }
/* The raw link stays one quiet line: the name and the buttons carry the row. */
input.url {
  margin-top: 6px; min-height: 32px; padding: 4px 10px; font: 0.75rem/1.3 var(--mono); color: var(--muted);
  background: var(--tag-2); border-color: var(--line); text-overflow: ellipsis;
}
input.url:hover { border-color: var(--line-strong); }
/* A wide screen puts name, link and buttons on one line: a long list of
   people stays short enough to work down. */
@media (min-width: 720px) {
  .links li {
    display: grid; grid-template-columns: minmax(7rem, 0.8fr) minmax(6rem, 1fr) auto;
    align-items: center; gap: 0 14px; padding: 8px 0;
  }
  .link-head { display: contents; }
  .who { grid-column: 1; grid-row: 1; }
  input.url { grid-column: 2; grid-row: 1; margin-top: 0; }
  .link-actions { grid-column: 3; grid-row: 1; flex-wrap: nowrap; }
}
#all-links { font: 0.8rem/1.45 var(--mono); min-height: 10rem; background: var(--tag-2); }

#forget-box, #forgotten { margin-top: 1.25rem; }

.offscreen { position: fixed; left: -9999px; top: 0; width: 1px; height: 1px; opacity: 0; }

/* ---------- the reveal: a tag hanging from a ribbon bow ---------- */

/* --knot is where the bow's knot sits; the ribbon is centred on it and the
   twine drops from it to the tag */
#reveal { --knot: 32px; --parcel-h: 92px; --bow-w: 240px; }
@media (min-width: 720px) { #reveal { --knot: 40px; --parcel-h: 112px; --bow-w: 300px; } }
.rv-parcel { position: relative; height: var(--parcel-h); margin-top: -6px; }
/* the parcel's ribbon, full width without widening the page (border-image
   outset is painted, not scrolled) */
.rv-parcel::before {
  content: ""; position: absolute; left: 0; right: 0; top: calc(var(--knot) - 13px); height: 26px;
  border-image:
    linear-gradient(to bottom,
      var(--band-edge) 0 1px, var(--band) 1px 4px, var(--gold) 4px 5px, var(--band) 5px calc(100% - 5px),
      var(--gold) calc(100% - 5px) calc(100% - 4px), var(--band) calc(100% - 4px) calc(100% - 1px), var(--band-edge) calc(100% - 1px))
    fill 0 // 0 100vmax;
}
.bow-art {
  position: absolute; z-index: 2; left: 50%; top: 0;
  width: var(--bow-w); height: auto; aspect-ratio: 240 / 78; transform: translateX(-50%);
}

.card {
  --cut: 30px;
  --hole-y: 36px;
  --hang: calc(var(--parcel-h) - var(--knot)); /* from the bow's knot down to the top of the tag */
  position: relative;
  max-width: 31rem;
  margin: 0 auto 18px;
  padding: 72px 20px 18px;
  text-align: center;
  color: var(--ink);
  border-radius: 0 0 8px 8px;
  box-shadow: 0 1px 0 var(--edge), 0 26px 34px -26px var(--shadow);
}
@media (min-width: 560px) { .card { padding: 76px 40px 22px; } }
.card::after {
  content: ""; position: absolute; z-index: 0;
  top: calc(var(--hole-y) - 17px); left: 50%; width: 34px; height: 34px; margin-left: -17px;
  border-radius: 50%;
  background: radial-gradient(circle closest-side, var(--page) 0 40%, var(--edge) 42% 48%, var(--ring) 50% 100%);
}
.card::before {
  content: ""; position: absolute; z-index: 1;
  top: calc(var(--hang) * -1 - 1px); left: 50%; width: 3px; margin-left: -1.5px;
  height: calc(var(--hang) + var(--hole-y) + 1px);
  border-radius: 2px;
  background: repeating-linear-gradient(-58deg, var(--twine-b) 0 1.6px, var(--twine-a) 1.6px 3.4px);
}
/* Closed, a wax seal holds the twine to the tag; opening the tag breaks it. */
.rv-seal {
  position: absolute; z-index: 2;
  top: calc(var(--hole-y) - 26px); left: 50%; width: 52px; height: 52px; margin-left: -26px;
}

.kicker {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  font-weight: 700; color: var(--cran);
  font-variant-caps: all-small-caps; letter-spacing: 0.16em; font-size: 1.02rem;
  margin: 0 0 0.6rem;
}
.kicker::before, .kicker::after { content: ""; height: 1px; width: 2.2rem; background: var(--gold); }

#rv-title, #rv-out-title, #rv-bad-title { text-wrap: balance; font-size: 1.2rem; font-style: italic; font-weight: 400; color: var(--muted); letter-spacing: 0; margin-bottom: 0.9rem; }
#rv-out-title, #rv-bad-title { font-style: normal; font-weight: 600; color: var(--ink); font-size: clamp(1.7rem, 6.5vw, 2.2rem); }
#rv-giver {
  display: block; font-style: normal; font-weight: 600; color: var(--ink);
  font-size: clamp(2.1rem, 9vw, 2.9rem); letter-spacing: -0.015em; line-height: 1.1; margin-top: 0.3rem;
}
#rv-closed > p:first-of-type { color: var(--muted); margin-bottom: 1.25rem; text-wrap: balance; }

.reveal-btn { max-width: 100%; margin-top: 0.25rem; min-height: 54px; padding: 12px 16px; text-wrap: balance; }
@media (min-width: 560px) { .reveal-btn { padding-left: 30px; padding-right: 30px; } }
@media (max-width: 559px) { .reveal-btn { width: 100%; } }
.notyou { margin: 0.8rem 0 0; font-size: 0.92rem; color: var(--muted); }

/* opened: the back of the tag, written by hand */
.tag-sprig { display: block; width: 120px; height: 40px; margin: -0.4rem auto 0.2rem; }
/* Sized so a 12-letter surname (Papadopoulos) fits on one line at 320 and 390
   px, and a 14-letter one (Schwarzenegger) on a wide screen. At 12vw and 4rem,
   Montgomery broke as "Montgomer / y" at 320 px and Featherstonehaugh at every
   width; only a name longer than that still breaks inside the word. */
.match { font-size: clamp(2.3rem, 11.5vw, 3.6rem); margin: 0.1rem 0 1.4rem; letter-spacing: -0.02em; line-height: 1.05; }
.match .lead { display: block; font: italic 400 1.2rem/1.4 var(--serif); letter-spacing: 0; color: var(--muted); margin-bottom: 0.4rem; }
#rv-match-name {
  display: inline-block; max-width: 100%; color: var(--name); padding: 0 0.06em 0.12em;
  border-bottom: 1px solid var(--gold);
}
.match:focus { outline: none; }
.match:focus-visible { outline: 3px solid var(--focus); outline-offset: 4px; }
/* Once the tag is turned over, the match leads: the "Secret Santa" label goes
   (the header says it) and whom the link is for steps back. */
#rv-card:has(#rv-opened:not([hidden])) .kicker { display: none; }
#rv-card:has(#rv-opened:not([hidden])) #rv-title { margin-bottom: 0.4rem; }
#rv-card:has(#rv-opened:not([hidden])) #rv-giver { display: inline; font-size: 1.2rem; letter-spacing: 0; }
.facts { margin: 0 auto 1.1rem; display: grid; gap: 0; max-width: 24rem; text-align: left; }
.facts > div { border-top: 1px solid var(--rule); padding: 9px 2px; display: grid; gap: 1px; }
.facts > div:last-child { border-bottom: 1px solid var(--rule); }
.facts dt { font-size: 0.95rem; color: var(--muted); font-weight: 600; font-variant-caps: all-small-caps; letter-spacing: 0.1em; }
.facts dd { margin: 0; white-space: pre-line; }
/* a wink, not a warning */
.keep { font: italic 400 1.25rem/1.4 var(--serif); color: var(--cran); margin: 0.3rem 0 0.9rem; }
#rv-opened .actions { justify-content: center; }
#rv-opened .actions button { flex: 1 1 9rem; max-width: 13rem; }
/* the tear-off strip: the only perforated line on the site */
.drawmeta {
  margin: 1.5rem -20px 0; padding: 12px 20px 0;
  border-top: 2px dashed var(--rule);
  font-size: 0.85rem; letter-spacing: 0.04em; color: var(--muted); font-variant-numeric: tabular-nums;
}
@media (min-width: 560px) { .drawmeta { margin-left: -40px; margin-right: -40px; } }
.card.warn { text-align: left; }
.card.warn .kicker { justify-content: flex-start; }
.card.warn .kicker::before { display: none; }
.aside { color: var(--ground-muted); text-align: center; margin-top: 1.25rem; }
.aside a { color: var(--ground-ink); font-weight: 600; }

/* on a wide screen the tag is the whole page, so it can be larger */
@media (min-width: 720px) {
  .card { max-width: 34rem; }
  #rv-giver { font-size: 3.2rem; }
  .match { font-size: 3.75rem; }
}
/* The tag turns over on its string when opened: a quarter turn in, no bounce. */
@media (prefers-reduced-motion: no-preference) {
  #rv-card:has(#rv-opened:not([hidden])) { animation: tag-turn 0.5s cubic-bezier(0.2, 0.75, 0.25, 1) both; }
}
@keyframes tag-turn {
  from { transform: perspective(1600px) rotateY(-88deg); }
  to { transform: perspective(1600px) rotateY(0deg); }
}

/* ---------- site: page body, prose, tables ---------- */

/* The column every page's content sits in, under the band. */
.page-body { padding-top: 8px; padding-bottom: 40px; }
.page-body > h2, .page-body > section > h2 { margin-top: 2rem; }
.page-body > h3 { margin-top: 1.4rem; }
/* Prose lists only: the tool's own lists (people, rules, links) have classes. */
.page-body > ul, .page-body > ol, .panel > ul:not([class]), .panel > ol:not([class]) { padding-left: 1.25rem; margin: 0 0 0.9rem; }
.page-body > ul > li, .page-body > ol > li, .panel > ul:not([class]) > li, .panel > ol:not([class]) > li { margin: 0 0 0.4rem; }
.page-body > ul > li::marker, .page-body > ol > li::marker, .panel > ul:not([class]) > li::marker, .panel > ol:not([class]) > li::marker { color: var(--cran); }
.page-body > p, .page-body > ul, .page-body > ol { color: var(--ground-ink); }
.page-body blockquote { margin: 1rem 0; padding: 0.2rem 0 0.2rem 1rem; border-left: 3px solid var(--gold); color: var(--ground-muted); }
.page-body figure { margin: 1rem 0; }
.page-body figcaption { color: var(--ground-muted); font-size: 0.92rem; margin-top: 0.4rem; }
.page-body img { max-width: 100%; height: auto; }

/* The answer-first element: a card laid on the sheet, right under the band. */
.answer { margin: 20px 0 8px; }
.answer.card-box, .answer:not(.answer-table):not(.tool) {
  background: var(--tag); color: var(--ink);
  border: 1px solid var(--tag-edge); border-radius: 6px;
  box-shadow: 0 1px 0 var(--edge), 0 14px 22px -18px var(--shadow);
  padding: 16px;
}
@media (min-width: 560px) { .answer:not(.answer-table):not(.tool) { padding: 20px 24px; } }

/* Tables: the plain answer table every page uses. Wrap a wide one in
   <div class="table-wrap"> so it scrolls inside itself on a phone. */
.table-wrap { overflow-x: auto; margin: 1rem 0; }
.page-body table {
  width: 100%; border-collapse: collapse; font-size: 0.97rem;
  background: var(--tag); color: var(--ink);
  border: 1px solid var(--tag-edge); border-radius: 6px;
}
.page-body caption {
  caption-side: top; text-align: left; padding: 0 0 8px;
  font: 600 1.15rem/1.3 var(--serif); color: var(--ground-ink);
}
.page-body th, .page-body td { text-align: left; vertical-align: top; padding: 10px 12px; border-bottom: 1px solid var(--rule); }
/* Whole words in table cells. The body's overflow-wrap: anywhere lets a column
   shrink below its longest word, so at 390 px cells broke mid-word
   ("Somethin / g sweet", "addresse / s"). break-word still wraps a single word
   wider than the whole cell. The Not secret list keeps anywhere (long names). */
.page-body th, .page-body td { word-break: normal; overflow-wrap: break-word; }
/* The narrowest phones (320 px): whole words need a little more room, so the
   cells give up some padding rather than make a table scroll sideways. */
@media (max-width: 359px) { .page-body th, .page-body td { padding: 8px 7px; } }
.page-body thead th { font-size: 0.9rem; color: var(--muted); letter-spacing: 0.06em; font-variant-caps: all-small-caps; border-bottom-color: var(--line-strong); }
.page-body tbody tr:last-child th, .page-body tbody tr:last-child td { border-bottom: 0; }
.page-body tbody th { font-weight: 600; }
.answer-table { margin-top: 28px; }
/* The tool's own tables (Not secret list) and the tutorial's keep their look. */
.tool table, .tut-table { background: none; border: 0; }

/* Utility pages: when they last changed, at the foot. */
.page-date { margin-top: 2rem; color: var(--ground-muted); font-size: 0.9rem; }

/* A section a writer hasn't written yet (data-stub): marked on screen so
   nobody mistakes the skeleton for the page. `npm run check -- --launch`
   refuses to pass while any is left. */
[data-stub] { outline: 2px dashed var(--cran); outline-offset: 3px; }

/* ---------- site: footer ---------- */

footer.site {
  border-top: 1px solid var(--edge); color: var(--ground-muted); font-size: 0.92rem;
  padding: 22px 0 36px;
  background: var(--ground-tex) 0 0 / 240px 240px, var(--band-bg);
}
footer.site p { margin: 0 0 0.6rem; }
footer.site a { color: var(--ground-ink); }
.footer-note { max-width: 34rem; }
.footer-nav { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: 16px 24px; margin: 18px 0 20px; }
.footer-h { font-weight: 700; color: var(--ground-ink); letter-spacing: 0.06em; font-variant-caps: all-small-caps; font-size: 1rem; margin: 0 0 0.35rem !important; }
.footer-nav ul { list-style: none; margin: 0; padding: 0; }
.footer-nav li { margin: 0; }
.footer-nav a { display: inline-block; padding: 5px 0; line-height: 1.35; }
.footer-util { display: flex; flex-wrap: wrap; gap: 4px 18px; border-top: 1px solid var(--edge); padding-top: 14px; }
.footer-util a { display: inline-block; padding: 4px 0; font-weight: 600; }
.reveal-page footer.site .footer-util { border-top: 0; padding-top: 0; }

/* ---------- site: the tool's additions ---------- */

/* Sending: WhatsApp, Text and Email open the person's own app with the
   message written. Links drawn as small buttons. */
a.send { font-weight: 600; }
a.button {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 8px 18px; border-radius: var(--radius);
  border: 1.5px solid var(--line-strong); background: var(--field); color: var(--ink);
  font-weight: 600; text-decoration: none; text-align: center;
}
a.button:hover { border-color: var(--ink); background: var(--tag-2); }
a.button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
a.button.primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--accent-ink); }
.link-actions a.button { min-width: 6.5rem; }
.send-via { margin: 6px 0 0; font-size: 0.92rem; color: var(--muted); display: flex; flex-wrap: wrap; align-items: center; gap: 0 14px; }
.send-via a { display: inline-flex; align-items: center; min-height: 36px; }
.send-via-label { margin-right: -4px; }
@media (min-width: 720px) {
  .links li > .send-via { grid-column: 1 / -1; grid-row: 2; margin-top: 2px; }
}
/* The WhatsApp page's Send next flow: sent rows are marked, the next one stands out. */
.sent-mark {
  display: inline-block; margin-left: auto; padding: 0 7px; vertical-align: 0.1em;
  border: 1.5px solid var(--link); border-radius: 3px; color: var(--link);
  font: 700 0.8rem/1.35 var(--sans); letter-spacing: 0.08em; font-variant-caps: all-small-caps;
}
[data-send-first] .links li[data-sent] .who { color: var(--muted); }
.links li[data-next] { background: var(--accent-soft); box-shadow: -8px 0 0 var(--accent-soft), 8px 0 0 var(--accent-soft); }

/* Secret / Not secret (the gift exchange page). */
.mode {
  margin: 20px 0 0; padding: 14px 16px 12px; border: 1px solid var(--tag-edge); border-radius: 6px;
  background: var(--tag); color: var(--ink); box-shadow: 0 1px 0 var(--edge);
}
.mode legend { float: left; width: 100%; padding: 0; margin: 0 0 8px; font: 600 1.1rem/1.3 var(--serif); }
.mode-opt { display: flex; gap: 10px; align-items: flex-start; font-weight: 400; margin: 6px 0; clear: both; }
.mode-opt input { width: 1.15rem; height: 1.15rem; margin: 0.2rem 0 0; accent-color: var(--accent); flex: none; }
.mode-d { display: block; color: var(--muted); font-size: 0.92rem; }
@media (min-width: 560px) {
  .mode { display: grid; grid-template-columns: 1fr 1fr; column-gap: 16px; }
  .mode legend { grid-column: 1 / -1; }
}
.mode ~ section.panel:first-of-type { --gap: 30px; }
.mode ~ section.panel:first-of-type::before {
  top: calc(var(--gap) * -1 - 1px); width: 3px; margin-left: -1.5px; height: calc(var(--gap) + var(--hole-y) + 1px);
  border-radius: 2px; background: repeating-linear-gradient(-58deg, var(--twine-b) 0 1.6px, var(--twine-a) 1.6px 3.4px);
}
.open-results { margin-top: 1.5rem; border-top: 1px solid var(--rule); padding-top: 1.1rem; }
.open-results h4 { margin-top: 0; font-size: 1.3rem; }
.open-results h4:focus { outline: none; }
.open-results h4:focus-visible { outline: 3px solid var(--focus); }
.open-details { list-style: none; padding: 0; margin: 0 0 0.75rem; color: var(--muted); }
.open-table { width: 100%; border-collapse: collapse; margin: 0.5rem 0 0.75rem; }
.open-table th, .open-table td { text-align: left; padding: 8px 10px 8px 0; border-bottom: 1px solid var(--rule); vertical-align: top; word-break: break-word; overflow-wrap: anywhere; }
.open-table thead th { font-size: 0.9rem; color: var(--muted); letter-spacing: 0.06em; font-variant-caps: all-small-caps; border-bottom-color: var(--line-strong); }
.open-table tbody th { font-weight: 600; }

/* Step 3: children, and what the cards call the game. */
.kids-check { margin-bottom: 0.2rem; }
.kids-help { margin: 0 0 0 1.65rem; }
.occasion-note { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; margin: 0 0 0.5rem; }
.occasion-note p { margin: 0; flex: 1 1 16rem; }

/* The link page without a card. */
.empty-card { text-align: left; }
.empty-card .kicker { justify-content: flex-start; }
.empty-card .kicker::before { display: none; }
#rv-empty-title { font-size: clamp(1.6rem, 6vw, 2.1rem); }

[hidden] { display: none !important; }
.print-only { display: none; }

@media print {
  /* Paper is white whatever the screen theme: these selectors match the dark
     theme's, so coming later they win over it (a bare :root would lose). */
  :root, :root:not([data-theme="light"]), :root[data-theme="dark"] {
    --bg: #fff; --ground: #fff; --paper: #fff; --band-bg: #fff; --ground-ink: #000; --ground-muted: #333;
    --tag: #fff; --tag-2: #fff; --tag-edge: #fff; --field: #fff; --surface: #fff; --ink: #000; --muted: #333;
    --line: #999; --rule: #999; --line-strong: #666; --gold: #666; --cran: #000; --name: #000; --link: #000;
    --accent: #000; --accent-soft: #fff; --warn-ink: #000; --warn-soft: #fff; --danger: #000; --danger-soft: #fff;
    /* The green button's own colours too: the dark theme's near-black label
       stayed on the black button, so "Draw again" printed unreadable. */
    --accent-hover: #000; --accent-ink: #fff;
    color-scheme: light;
  }
  body { background: #fff; color: #000; font-size: 12pt; }
  header.site, footer.site, .no-print, .aside, .rv-parcel, .hero-art, .tag-sprig, .crumbs, .skip { display: none !important; }
  .page-head { background: none; border: 0; padding: 0; }
  [data-stub] { outline: none; }
  /* "Print list" on the gift exchange page: the list and nothing else, at the
     top of page 1. Hiding with visibility kept the hidden content's space, so
     in Chromium the list printed alone in the middle of page 2 of 3
     (2026-09-27). Everything that isn't the list or one of its ancestors is
     taken out of the layout, and the ancestors lose their spacing. The
     visibility rules stay for browsers without :has(). */
  body.print-open-list * { visibility: hidden; }
  body.print-open-list #open-results, body.print-open-list #open-results * { visibility: visible; }
  body.print-open-list #open-results { position: absolute; left: 0; top: 0; width: 100%; border: 0; margin: 0; padding: 0; }
  body.print-open-list *:not(:has(#open-results)):not(#open-results):not(#open-results *) { display: none !important; }
  body.print-open-list :has(#open-results) {
    margin: 0 !important; padding: 0 !important; border: 0 !important;
    min-height: 0 !important; box-shadow: none !important; background: none !important;
  }
  body.print-open-list #open-results { position: static !important; }
  .hero::before, .hero::after { display: none; }
  .print-only { display: block; }
  main.wrap { padding-top: 0; padding-bottom: 0; }
  /* A card opened with the keyboard has focus on the match: no focus ring on paper. */
  * { outline: none !important; }
  .panel, .card { background: #fff; box-shadow: none; }
  .panel::before, .panel::after, .card::before { display: none; }
  .panel { border: 1px solid #999; border-radius: 0; margin-top: 16px; }
  .card { border: 2px solid #000; border-radius: 0; max-width: 16cm; margin: 1cm auto; break-inside: avoid; transform: none !important; }
  .card::after { background: radial-gradient(circle closest-side, #fff 0 42%, #000 46% 56%, #fff 60%); }
  .match { font-size: 30pt; }
  #rv-match-name { border-bottom-color: #000; }
  .keep { color: #000; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ---------- illustration colours (inline SVG, so they follow the theme) ---------- */
.ill-pine { fill: var(--i-pine); } .ill-pine-dk { fill: var(--i-pine-dk); } .ill-dot { fill: var(--i-dot); opacity: 0.28; }
.ill-cream { fill: var(--i-cream); } .ill-cream-shade { fill: var(--i-cream-shade); stroke: var(--i-cream-shade); } .ill-cream-knot { fill: var(--i-cream-knot); }
.ill-kraft { fill: var(--i-kraft); } .ill-kraft-dk { fill: var(--i-kraft-dk); } .ill-fibre { stroke: var(--i-fibre); opacity: 0.6; }
.ill-lid-shadow { fill: #000; opacity: 0.12; }
.ill-twine-a { stroke: var(--twine-a); } .ill-twine-b { stroke: var(--twine-b); } .ill-twine-knot { fill: var(--twine-b); }
.ill-string { stroke: var(--i-string); } .ill-tag-ring { fill: var(--ring); } .ill-hole { fill: var(--i-kraft); } .ill-tag-line { stroke: var(--i-tag-line); }
.ill-cran { fill: var(--i-cran); } .ill-cran-dk { fill: var(--i-cran-dk); stroke: var(--i-cran-dk); } .ill-cran-stripe { fill: var(--i-cran-stripe); } .ill-cran-knot { fill: var(--i-cran-knot); }
.ill-seal-rim { stroke: var(--i-cran-dk); } .ill-seal-hi { stroke: var(--i-cran-stripe); } .ill-seal-press { fill: var(--i-cran-dk); stroke: var(--i-cran-dk); }
.ill-gold-line { stroke: var(--gold); }
.ill-stem { stroke: var(--i-stem); } .ill-needle { stroke: var(--i-needle); } .ill-needle2 { stroke: var(--i-needle2); }
.ill-holly { fill: var(--i-holly); } .ill-holly-vein { stroke: var(--i-holly-vein); } .ill-berry { fill: var(--i-berry); } .ill-berry-hi { fill: var(--i-berry-hi); opacity: 0.55; }
.ill-shadow { fill: var(--i-shadow); }
